@magic/types 0.1.38 → 0.1.40

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
@@ -45,6 +45,19 @@ import is from '@magic/types'
45
45
  is.array([]) // true
46
46
  ```
47
47
 
48
+ ##### import deep
49
+
50
+ ```javascript
51
+ import { deep } from '@magic/types'
52
+
53
+ deep.isDeepEqual([1, 2, 3], [1, 2, 3]) // true
54
+ // also: deep.deepEqual, deep.deepEq, is.isDeepEqual
55
+ deep.isDeepDifferent([1, 2, 3], [1, 2, 3]) // false
56
+ // also: deep.deepDifferent, deep.deepDiff, is.isDeepDifferent
57
+ deep.isEqual([1, 2, 3], [1, 2, 3]) // true
58
+ // also: is.deep.isEqual, is.deep.equal, is.deep.eq
59
+ ```
60
+
48
61
  ##### functions
49
62
 
50
63
  ```javascript
@@ -52,13 +65,20 @@ is.array([]) // true
52
65
  // comparisons
53
66
 
54
67
  // test a value for multiple types
55
- is(ele, ...types)
56
- // alias is.eq, isEq, test
68
+ is.is(ele, ...types)
69
+ // alias is.type, is.testType, is.types, test
57
70
 
58
71
  // test if a value is not of a type
59
72
  not(ele, ...types)
60
73
  // alias is.neq, isNeq, isNot
61
74
 
75
+ // not (and is.not) is also a namespace with negated versions of every check:
76
+ is.not.array([]) // false
77
+ is.not.len.eq('abc', 'def') // false
78
+ is.not.case.upper('lowercase') // true
79
+ is.not.deep.eq([1], [1]) // false
80
+ is.not.ip.v4('192.168.1.1') // false
81
+
62
82
  isSameType('string', 'string')
63
83
  // alias isSame, is.same, is.sameType
64
84
 
@@ -74,7 +94,7 @@ isBoolean(true) // true
74
94
  isDefined(undefined) //false
75
95
  // alias isDef, is.defined, is.def
76
96
 
77
- isUndefined(undefined) //false
97
+ isUndefined(undefined) //true
78
98
  // alias isUndef, is.undefined, is.undef
79
99
 
80
100
  isFunction(() => {}) // true
@@ -84,7 +104,7 @@ isAsyncFunction(async () => {}) // true
84
104
  // alias isAsyncFunc, isAsyncFn, is.asyncFunction, is.asyncFunc, is.asyncFn
85
105
 
86
106
  isGeneratorFunction(* () => {}) // true
87
- // alias isGeneratorFunc, isGeneratorFunc, is.generatorFunction, is.generatorFunc, is.generatorFn
107
+ // alias isGeneratorFunc, isGeneratorFn, isGenerator, is.generatorFunction, is.generatorFunc, is.generatorFn, generator, generatorFn, generatorFunc, generatorFunction
88
108
 
89
109
  isNumber(1) // true
90
110
  // alias isNum, is.number, is.num
@@ -98,21 +118,41 @@ isFloat(1.1) // true
98
118
  isObject({}) // true
99
119
  // alias isObj, is.object, is.obj
100
120
 
121
+ isObjectNative({}) // true
122
+ isObjectNative([]) // false
123
+ // alias is.objectNative
124
+
101
125
  isString('') // true
102
126
  // alias isStr, is.string, is.str
103
127
 
104
128
  isRGBAObject({ r: 1, g: 1, b: 1, a: 1 }) // true
105
129
  // alias isRGBA, is.rgbaObject, is.rgba
106
130
 
107
- isRGBObject
131
+ isRGBObject({ r: 1, g: 1, b: 1 }) // true
108
132
  // alias isRGB, is.rgbObject, is.rgb
109
133
 
134
+ isRGBValue({ r: 1, g: 1, b: 1 }) // true
135
+ // alias isRGBObject, is.rgbValue
136
+
137
+ isRGBAValue({ r: 1, g: 1, b: 1, a: 1 }) // true
138
+ // alias isRGBAObject, is.rgbaValue
139
+
110
140
  isHexColor('#333') // true
111
141
  // alias isHex, is.hex, is.hexColor
112
142
 
143
+ isHexColor3('#333') // true
144
+ isHexColor4('#3333') // true
145
+ isHexColor6('#333333') // true
146
+ isHexColor8('#33333333') // true
147
+ // aliases is.hex3, is.hexColor3, is.hex4, is.hexColor4, is.hex6, is.hexColor6, is.hex8, is.hexColor8
148
+
113
149
  isHexAlphaColor('#3333') // true
114
150
  // alias isHexa, is.hexa, is.hexAlphaColor
115
151
 
152
+ isHexAlphaColor4('#3333') // true
153
+ isHexAlphaColor8('#33333333') // true
154
+ // aliases is.hexa4, is.hexAlphaColor4, is.hexa8, is.hexAlphaColor8
155
+
116
156
  isColor('#444') // true
117
157
  // alias isCol, is.color, is.col
118
158
 
@@ -135,52 +175,89 @@ isError(new Error('')) // true
135
175
  // alias isErr, is.error, is.err
136
176
 
137
177
  isIterable([]) // true
138
- // alias is.iterable
178
+ // alias is.iterable, is.iter, isIter
139
179
 
140
180
  isEmail('a@b.c') // true
141
181
  // alias isMail, is.email, is.mail
142
182
 
183
+ isIP('192.168.1.1') // true
184
+ isIP('::1') // true
185
+ // alias ip, is.ip, isIp, isIP
186
+
187
+ isIp('192.168.1.1') // true
188
+ isIp('::1') // true
189
+ // alias ip, is.ip
190
+
191
+ isIp.v4('192.168.1.1') // true
192
+ isIp.v6('::1') // true
193
+
194
+ isIPv4('192.168.1.1') // true
195
+ // aliases ipV4, is.ipV4, is.ipv4, is.v4
196
+
197
+ isIPv6('::1') // true
198
+ // aliases ipV6, is.ipV6, is.ipv6, is.v6
199
+
200
+ isMap(new Map()) // true
201
+ // alias is.map, is.map, map
202
+
203
+ isSet(new Set()) // true
204
+ // alias is.set, is.set, set
205
+
206
+ isWeakMap(new WeakMap()) // true
207
+ // alias is.weakMap, is.weakMap, weakMap
208
+
209
+ isWeakSet(new WeakSet()) // true
210
+ // alias is.weakSet, is.weakSet, weakSet
211
+
143
212
  isNull(null) // true
144
213
  // alias isNil, is.nil, is.null
145
214
 
146
215
  isUndefinedOrNull(undefined || null) // true
147
216
  // alias is.undefinedOrNull, is.undefinedOrNil, is.undefOrNull, is.undefOrNil
148
217
 
149
- isBuffer(new Buffer('test')) // true
218
+ isBuffer(Buffer.from('test')) // true
150
219
  // alias isBuff, is.buffer, is.buff
151
220
 
152
- isPromise(new Promise()) // true
221
+ isPromise(new Promise(r => r())) // true
153
222
  // alias is.promise, isThenable, isThen, is.thenable, is.then
154
223
 
155
- // removed (for now?)!
156
- isArguments(() => return arguments) // true
224
+ // (call with a function's arguments object)
225
+ (function () {
226
+ isArguments(arguments) // true
227
+ })()
157
228
  // alias isArgs, is.arguments, is.args
158
229
 
159
230
  isUUID(uuid) // true
160
231
  // alias is.uuid
161
232
 
162
- testType(42, 'number') // true
163
- // alias is.type
233
+ isType(42, 'number') // true
234
+ // alias is.type, is.testType, isType
164
235
 
165
- test(42, ['string', 'object']) // false
236
+ is.test(42, ['string', 'object']) // false
166
237
  // alias is.types
167
238
 
168
- isEq(42, 'number') // true
239
+ is.eq('abc', 'def') // true
169
240
  // alias is.eq
241
+ // is.eq compares lengths, see "length" section below
170
242
 
171
- isNot = isNeq = is.not(42, 'number') // true
243
+ isNot = isNeq = is.not(42, 'string') // true
172
244
  // alias is.neq
173
245
 
174
- isDeepEqual([1, 2, 3], [1, 2, 3]) // true
246
+ deep.isDeepEqual([1, 2, 3], [1, 2, 3]) // true
175
247
  // alias is.deep.eq, is.deep.equal
176
- isDeepDifferent([1, 2, 3], [1, 2, 3]) // false
248
+ // also deep.deepEqual, deep.deepEq, is.isDeepEqual
249
+ deep.isDeepDifferent([1, 2, 3], [1, 2, 3]) // false
177
250
  // alias is.deep.diff, is.deep.different
251
+ // also deep.deepDifferent, deep.deepDiff, is.isDeepDifferent
252
+
253
+ deep.isDifferent([1, 2, 3], [1, 2, 3]) // false
254
+ // alias is.deep.isDifferent, is.deep.different, is.deep.diff
178
255
 
179
- isDeepEqual([1, 2, 3], [3, 2, 1]) // true
180
- isDeepEqual([1, 2, 3], [3, 2, 1], { strict: true }) // false
256
+ deep.isDeepEqual([1, 2, 3], [3, 2, 1]) // true
257
+ deep.isDeepEqual([1, 2, 3], [3, 2, 1], { strict: true }) // false
181
258
 
182
- isDeepEqual({a: 1, b: 2, c: 3 }, { c: 3, b: 2, a: 1 }) // true
183
- isDeepEqual({a: 1, b: 2, c: 3 }, { c: 3, b: 2, a: 1 }, { strict: true }) // false
259
+ deep.isDeepEqual({a: 1, b: 2, c: 3 }, { c: 3, b: 2, a: 1 }) // true
260
+ deep.isDeepEqual({a: 1, b: 2, c: 3 }, { c: 3, b: 2, a: 1 }, { strict: true }) // false
184
261
 
185
262
  isEvery([1, 2, 3], 'number') // true
186
263
  isEvery([1, 2, 3], is.number) // true
@@ -190,7 +267,7 @@ isSome([1, 'str', {}], 'number') // true
190
267
  isSome([1, 'str', {}], is.number) // true
191
268
  // alias is.some
192
269
 
193
- isSymbol(Symbol('testing)) // true
270
+ isSymbol(Symbol('testing')) // true
194
271
  // alias is.symbol, is.sym
195
272
 
196
273
  isNone([1, 2, 3], 'string') // true
@@ -205,10 +282,10 @@ isCase('lowercase', 'low') // true
205
282
  // alias is.case
206
283
 
207
284
  isUpperCase('UPPERCASE') // true
208
- // alias is.case.upper, is.isCase.upper
285
+ // alias is.case.upper, isCase.upper
209
286
 
210
287
  isLowerCase('lowercase') // true
211
- // alias is.case.lower, is.isCase.lower
288
+ // alias is.case.lower, isCase.lower
212
289
 
213
290
  isMergeableObject({}) // true
214
291
  // alias is.mergeable, is.mergeableObject, isMergeable
@@ -217,9 +294,47 @@ const mod = await import('path/to/file')
217
294
  isModule(mod) // true
218
295
  // alias is.module
219
296
 
297
+ isComparable(1) // true
298
+ isComparable('str') // true
299
+ isComparable(true) // true
300
+ isComparable({}) // false
301
+ // aliases is.comparable, is.Comparable
302
+
220
303
  isOwnProp({ test: undefined }, 'test') // true
221
304
  // alias isOwnProperty, is.ownProperty, is.ownProp, is.prop
222
305
 
306
+ // length
307
+
308
+ // get the length of a string, array, map, set, regexp, or object
309
+ // numbers return themselves
310
+ getLength('test') // 4
311
+ getLength([1, 2, 3]) // 3
312
+ getLength(new Set([1, 2])) // 2
313
+ getLength(123) // 123
314
+ // aliases is.len, is.count, is.length, is.ln
315
+
316
+ // compare lengths, both arguments can be anything with a length
317
+ // these can also be curried: is.gt('abcd')('ab') // true
318
+ is.eq('abc', 'def') // true
319
+ is.gt('abcd', 'ab') // true
320
+ is.gte('abc', 'ab') // true
321
+ is.lt('ab', 'abc') // true
322
+ is.lte('abc', 'abc') // true
323
+ // aliases is.equal, is.greater, is.bigger, is.greaterequal, is.biggerequal,
324
+ // is.gteq, is.lower, is.smaller, is.lowerequal, is.smallerequal, is.lteq
325
+
326
+ isLengthEqual('abc', 3) // true
327
+ isLengthGreater('abc', 2) // true
328
+ isLengthGreaterOrEqual('ab', 2) // true
329
+ isLengthSmaller('ab', 3) // true
330
+ isLengthSmallerOrEqual('abc', 3) // true
331
+ // aliases is.isLengthEqual, is.isLengthGreater, is.isLengthGreaterOrEqual,
332
+ // is.isLengthSmaller, is.isLengthSmallerOrEqual
333
+
334
+ compareCount('abc', 3) // true
335
+
336
+ // the length functions also exist as methods on the length checks:
337
+ is.len.eq('abc', 'def') // true
223
338
  ```
224
339
 
225
340
  #### Changelog
@@ -407,6 +522,17 @@ update dependencies
407
522
  - remove recursive dependencies
408
523
  - update dependencies
409
524
 
410
- ##### 0.1.39 - unreleased
525
+ ##### 0.1.39
526
+
527
+ - add isIp and variants to allow ip v4 and v6 checks
528
+ - update dependencies
529
+
530
+ ##### 0.1.40
531
+
532
+ - add is.not negations of all type functions
533
+ - update docs
534
+ - update dependencies
535
+
536
+ ##### 0.1.41 - unreleased
411
537
 
412
538
  ...
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magic/types",
3
- "version": "0.1.38",
3
+ "version": "0.1.40",
4
4
  "author": "Wizards & Witches",
5
5
  "homepage": "https://github.com/magic/types",
6
6
  "license": "AGPL-3.0",
@@ -27,7 +27,8 @@
27
27
  "format": "f -w --exclude docs",
28
28
  "format:check": "f --exclude docs",
29
29
  "calls": "calls",
30
- "lint": "tsc --noEmit"
30
+ "lint": "tsc --noEmit",
31
+ "lint:test": "tsc --noEmit -p tsconfig.test.json"
31
32
  },
32
33
  "engines": {
33
34
  "node": ">=18"
@@ -50,10 +51,10 @@
50
51
  "@magic-modules/no-spy": "0.0.9",
51
52
  "@magic-modules/pre": "0.0.12",
52
53
  "@magic-themes/docs": "0.0.15",
53
- "@magic/core": "0.0.159",
54
- "@magic/format": "0.0.74",
55
- "@magic/test": "0.3.21",
56
- "typescript": "6.0.3"
54
+ "@magic/core": "0.0.160",
55
+ "@magic/format": "0.0.75",
56
+ "@magic/test": "0.3.32",
57
+ "typescript": "npm:@typescript/typescript6"
57
58
  },
58
59
  "keywords": [
59
60
  "magic",
@@ -67,10 +68,10 @@
67
68
  }
68
69
  ],
69
70
  "dependencies": {
70
- "@types/node": "26.0.1"
71
+ "@types/node": "26.6.3"
71
72
  },
72
73
  "allowScripts": {
73
- "@swc/core@1.3.41": true,
74
- "canvas@3.2.3": true
74
+ "canvas@3.2.3": true,
75
+ "@swc/core@1.15.46": true
75
76
  }
76
77
  }
package/src/deep/index.js CHANGED
@@ -11,10 +11,10 @@ export const deepDiff = different
11
11
 
12
12
  export const deep = {
13
13
  isDifferent: different,
14
- different: different,
14
+ different,
15
15
  diff: different,
16
16
 
17
17
  isEqual: equal,
18
- equal: equal,
18
+ equal,
19
19
  eq: equal,
20
20
  }
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/index.js CHANGED
@@ -4,5 +4,6 @@ export * from './fns.js'
4
4
  export * as deep from './deep/index.js'
5
5
 
6
6
  export const is = def
7
+ export const not = is.not
7
8
 
8
9
  export default is
package/src/lib.js CHANGED
@@ -30,6 +30,16 @@ import * as deep from './deep/index.js'
30
30
  * }} EnhancedLengthFunction
31
31
  */
32
32
 
33
+ /**
34
+ * The `is.not` namespace: the original `isNot` check function, extended at
35
+ * runtime (by `addNotFunctions`) with a negated version of every `is.*` check
36
+ * and their nested sub-checks (e.g. `.upper`, `.eq`, `.v4`, `deep`). Each
37
+ * added property is either a negated check function or an object of them.
38
+ * @typedef {((e: unknown, ...types: string[]) => boolean) & {
39
+ * [key: string]: any
40
+ * }} NotNamespace
41
+ */
42
+
33
43
  // Create enhanced length functions with comparison methods
34
44
  const lengthFunctions = {
35
45
  eq: fns.isLengthEqual,
@@ -126,7 +136,7 @@ export const is = /** @type {const} */ {
126
136
  empty: fns.isEmpty,
127
137
 
128
138
  isNot: fns.isNot,
129
- not: fns.isNot,
139
+ not: /** @type {NotNamespace} */ (fns.isNot),
130
140
  isNeq: fns.isNot,
131
141
  neq: fns.isNot,
132
142
 
@@ -315,6 +325,18 @@ export const is = /** @type {const} */ {
315
325
  isLowerCase: fns.isLowerCase,
316
326
  lowerCase: fns.isLowerCase,
317
327
 
328
+ isIp: fns.isIp,
329
+ ip: fns.isIp,
330
+ isIPv4: fns.isIPv4,
331
+ ipv4: fns.isIPv4,
332
+ v4: fns.isIPv4,
333
+ isIPv6: fns.isIPv6,
334
+ ipv6: fns.isIPv6,
335
+ v6: fns.isIPv6,
336
+
337
+ ipV4: fns.ipV4,
338
+ ipV6: fns.ipV6,
339
+
318
340
  same: fns.isSameType,
319
341
  sameType: fns.isSameType,
320
342
  isSameType: fns.isSameType,
@@ -331,4 +353,98 @@ export const is = /** @type {const} */ {
331
353
  ...deep,
332
354
  }
333
355
 
356
+ /**
357
+ * Negation helper: creates a function that returns the logical NOT of fn
358
+ * @param {any} fn - function to negate
359
+ * @returns {(...args: any[]) => boolean} - negated function
360
+ */
361
+ const negate =
362
+ fn =>
363
+ (...args) =>
364
+ !fn(...args)
365
+
366
+ /**
367
+ * Add negated functions to the existing is.not namespace
368
+ * @param {any} obj - source object (the is namespace)
369
+ * @param {any} target - target object (the is.not namespace)
370
+ */
371
+ const addNotFunctions = (obj, target) => {
372
+ // Skip certain properties that shouldn't be copied
373
+ const skipKeys = new Set(['length', 'name', 'prototype', 'caller', 'callee', 'arguments'])
374
+
375
+ for (const [key, value] of Object.entries(obj)) {
376
+ if (key === 'not' || skipKeys.has(key)) continue
377
+ if (fns.isFunction(value)) {
378
+ target[key] = negate(value)
379
+ // Handle function sub-properties (e.g., isCase.upper, isIp.v4)
380
+ if (value.upper) {
381
+ target[key].upper = negate(value.upper)
382
+ }
383
+ if (value.lower) {
384
+ target[key].lower = negate(value.lower)
385
+ }
386
+ if (value.v4) {
387
+ target[key].v4 = negate(value.v4)
388
+ }
389
+ if (value.v6) {
390
+ target[key].v6 = negate(value.v6)
391
+ }
392
+ // Handle all length comparison functions
393
+ if (value.eq) {
394
+ target[key].eq = negate(value.eq)
395
+ }
396
+ if (value.equal) {
397
+ target[key].equal = negate(value.equal)
398
+ }
399
+ if (value.gt) {
400
+ target[key].gt = negate(value.gt)
401
+ }
402
+ if (value.bigger) {
403
+ target[key].bigger = negate(value.bigger)
404
+ }
405
+ if (value.biggerequal) {
406
+ target[key].biggerequal = negate(value.biggerequal)
407
+ }
408
+ if (value.greater) {
409
+ target[key].greater = negate(value.greater)
410
+ }
411
+ if (value.greaterequal) {
412
+ target[key].greaterequal = negate(value.greaterequal)
413
+ }
414
+ if (value.gte) {
415
+ target[key].gte = negate(value.gte)
416
+ }
417
+ if (value.gteq) {
418
+ target[key].gteq = negate(value.gteq)
419
+ }
420
+ if (value.lower) {
421
+ target[key].lower = negate(value.lower)
422
+ }
423
+ if (value.smaller) {
424
+ target[key].smaller = negate(value.smaller)
425
+ }
426
+ if (value.lt) {
427
+ target[key].lt = negate(value.lt)
428
+ }
429
+ if (value.lowerequal) {
430
+ target[key].lowerequal = negate(value.lowerequal)
431
+ }
432
+ if (value.smallerequal) {
433
+ target[key].smallerequal = negate(value.smallerequal)
434
+ }
435
+ if (value.lte) {
436
+ target[key].lte = negate(value.lte)
437
+ }
438
+ if (value.lteq) {
439
+ target[key].lteq = negate(value.lteq)
440
+ }
441
+ } else if (fns.isObjectNative(value)) {
442
+ target[key] = {}
443
+ addNotFunctions(value, target[key])
444
+ }
445
+ }
446
+ }
447
+
448
+ addNotFunctions(is, is.not)
449
+
334
450
  export default is
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
@@ -234,7 +234,7 @@ export const is: {
234
234
  isEmpty: (e: unknown) => boolean
235
235
  empty: (e: unknown) => boolean
236
236
  isNot: (e: unknown, ...types: string[]) => boolean
237
- not: (e: unknown, ...types: string[]) => boolean
237
+ not: import('./lib.js').NotNamespace
238
238
  isNeq: (e: unknown, ...types: string[]) => boolean
239
239
  neq: (e: unknown, ...types: string[]) => boolean
240
240
  isArray: (e: unknown) => e is unknown[]
@@ -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
@@ -751,4 +769,5 @@ export const is: {
751
769
  (a: unknown): (c: unknown) => boolean
752
770
  }
753
771
  }
772
+ export const not: import('./lib.js').NotNamespace
754
773
  export default is
package/types/lib.d.ts CHANGED
@@ -232,7 +232,7 @@ export const is: {
232
232
  isEmpty: (e: unknown) => boolean
233
233
  empty: (e: unknown) => boolean
234
234
  isNot: (e: unknown, ...types: string[]) => boolean
235
- not: (e: unknown, ...types: string[]) => boolean
235
+ not: NotNamespace
236
236
  isNeq: (e: unknown, ...types: string[]) => boolean
237
237
  neq: (e: unknown, ...types: string[]) => boolean
238
238
  isArray: (e: unknown) => e is unknown[]
@@ -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
@@ -769,4 +787,13 @@ export type EnhancedLengthFunction = typeof fns.getLength & {
769
787
  lte: LengthComparison
770
788
  lteq: LengthComparison
771
789
  }
790
+ /**
791
+ * The `is.not` namespace: the original `isNot` check function, extended at
792
+ * runtime (by `addNotFunctions`) with a negated version of every `is.*` check
793
+ * and their nested sub-checks (e.g. `.upper`, `.eq`, `.v4`, `deep`). Each
794
+ * added property is either a negated check function or an object of them.
795
+ */
796
+ export type NotNamespace = ((e: unknown, ...types: string[]) => boolean) & {
797
+ [key: string]: any
798
+ }
772
799
  import * as fns from './fns.js'