cidr-tools 11.0.10 → 11.0.11
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/dist/index.d.ts +26 -24
- package/dist/index.js +311 -331
- package/package.json +12 -11
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//#region index.d.ts
|
|
1
2
|
type IPv4Address = string;
|
|
2
3
|
type IPv6Address = string;
|
|
3
4
|
type IPv4CIDR = string;
|
|
@@ -6,38 +7,39 @@ type Network = IPv4Address | IPv4CIDR | IPv6Address | IPv6CIDR;
|
|
|
6
7
|
type Networks = Network | Array<Network>;
|
|
7
8
|
type ValidIpVersion = 4 | 6;
|
|
8
9
|
type ParsedCidr = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
cidr: string;
|
|
11
|
+
ip: string;
|
|
12
|
+
version: ValidIpVersion;
|
|
13
|
+
prefix: string;
|
|
14
|
+
prefixPresent: boolean;
|
|
15
|
+
start: bigint;
|
|
16
|
+
end: bigint;
|
|
16
17
|
};
|
|
17
18
|
type NormalizeOpts = {
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
compress?: boolean;
|
|
20
|
+
hexify?: boolean;
|
|
20
21
|
};
|
|
21
22
|
/** Returns a string or array (depending on input) with a normalized representation. Will not include a prefix on single IPs. Will set network address to the start of the network. */
|
|
22
|
-
|
|
23
|
+
declare function normalizeCidr<T extends Network | Array<Network>>(cidr: T, opts?: NormalizeOpts): T;
|
|
23
24
|
/** Returns a `parsed` Object which is used internally by this module. It can be used to test whether the passed network is IPv4 or IPv6 or to work with the BigInts directly. */
|
|
24
|
-
|
|
25
|
+
declare function parseCidr(str: Network): ParsedCidr;
|
|
25
26
|
/** Returns an array of merged networks */
|
|
26
|
-
|
|
27
|
+
declare function mergeCidr(nets: Networks): Array<Network>;
|
|
27
28
|
/** Returns an array of merged remaining networks of the subtraction of `excludeNetworks` from `baseNetworks`. */
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
declare function excludeCidr(base: Networks, excl: Networks): Array<Network>;
|
|
30
|
+
declare function expandCidr(nets: Networks): Generator<Network>;
|
|
30
31
|
/** Returns a boolean that indicates if `networksA` overlap (intersect) with `networksB`. */
|
|
31
|
-
|
|
32
|
+
declare function overlapCidr(a: Networks, b: Networks): boolean;
|
|
32
33
|
/** Returns a boolean that indicates whether `networksA` fully contain all `networksB`. */
|
|
33
|
-
|
|
34
|
+
declare function containsCidr(a: Networks, b: Networks): boolean;
|
|
34
35
|
declare const _default: {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
mergeCidr: typeof mergeCidr;
|
|
37
|
+
excludeCidr: typeof excludeCidr;
|
|
38
|
+
expandCidr: typeof expandCidr;
|
|
39
|
+
overlapCidr: typeof overlapCidr;
|
|
40
|
+
containsCidr: typeof containsCidr;
|
|
41
|
+
normalizeCidr: typeof normalizeCidr;
|
|
42
|
+
parseCidr: typeof parseCidr;
|
|
42
43
|
};
|
|
43
|
-
|
|
44
|
+
//#endregion
|
|
45
|
+
export { containsCidr, _default as default, excludeCidr, expandCidr, mergeCidr, normalizeCidr, overlapCidr, parseCidr };
|
package/dist/index.js
CHANGED
|
@@ -1,362 +1,342 @@
|
|
|
1
|
-
import { parseIp, stringifyIp
|
|
2
|
-
|
|
1
|
+
import { normalizeIp, parseIp, stringifyIp } from "ip-bigint";
|
|
2
|
+
|
|
3
|
+
//#region index.ts
|
|
4
|
+
const bits = {
|
|
5
|
+
4: 32,
|
|
6
|
+
6: 128
|
|
7
|
+
};
|
|
3
8
|
function uniq(arr) {
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
const set = new Set(arr);
|
|
10
|
+
return set.size === arr.length ? arr : Array.from(set);
|
|
6
11
|
}
|
|
7
12
|
function doNormalize(cidr, { compress = true, hexify = false } = {}) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const { start, end, prefix, version, prefixPresent } = parseCidr(cidr);
|
|
14
|
+
if (start !== end || prefixPresent) return `${normalizeIp(stringifyIp({
|
|
15
|
+
number: start,
|
|
16
|
+
version
|
|
17
|
+
}), {
|
|
18
|
+
compress,
|
|
19
|
+
hexify
|
|
20
|
+
})}/${prefix}`;
|
|
21
|
+
else return normalizeIp(cidr, {
|
|
22
|
+
compress,
|
|
23
|
+
hexify
|
|
24
|
+
});
|
|
15
25
|
}
|
|
26
|
+
/** Returns a string or array (depending on input) with a normalized representation. Will not include a prefix on single IPs. Will set network address to the start of the network. */
|
|
16
27
|
function normalizeCidr(cidr, opts) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
} else {
|
|
20
|
-
return doNormalize(cidr, opts);
|
|
21
|
-
}
|
|
28
|
+
if (Array.isArray(cidr)) return cidr.map((entry) => normalizeCidr(entry, opts));
|
|
29
|
+
else return doNormalize(cidr, opts);
|
|
22
30
|
}
|
|
31
|
+
/** Returns a `parsed` Object which is used internally by this module. It can be used to test whether the passed network is IPv4 or IPv6 or to work with the BigInts directly. */
|
|
23
32
|
function parseCidr(str) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
parsed.end = number | mask;
|
|
56
|
-
return parsed;
|
|
33
|
+
const parsed = Object.create(null);
|
|
34
|
+
const slashIndex = str.indexOf("/");
|
|
35
|
+
let ipPart;
|
|
36
|
+
let prefix;
|
|
37
|
+
if (slashIndex !== -1) {
|
|
38
|
+
ipPart = str.substring(0, slashIndex);
|
|
39
|
+
prefix = str.substring(slashIndex + 1);
|
|
40
|
+
if (!/^[0-9]+$/.test(prefix)) throw new Error(`Network is not a CIDR or IP: "${str}"`);
|
|
41
|
+
parsed.prefixPresent = true;
|
|
42
|
+
} else {
|
|
43
|
+
ipPart = str;
|
|
44
|
+
parsed.prefixPresent = false;
|
|
45
|
+
prefix = "";
|
|
46
|
+
}
|
|
47
|
+
const { number, version, ipv4mapped, scopeid } = parseIp(ipPart);
|
|
48
|
+
if (!version) throw new Error(`Network is not a CIDR or IP: "${str}"`);
|
|
49
|
+
if (!parsed.prefixPresent) prefix = String(bits[version]);
|
|
50
|
+
parsed.version = version;
|
|
51
|
+
parsed.ip = stringifyIp({
|
|
52
|
+
number,
|
|
53
|
+
version,
|
|
54
|
+
ipv4mapped,
|
|
55
|
+
scopeid
|
|
56
|
+
});
|
|
57
|
+
parsed.cidr = `${parsed.ip}/${prefix}`;
|
|
58
|
+
parsed.prefix = prefix;
|
|
59
|
+
const hostBits = bits[version] - Number(prefix);
|
|
60
|
+
const mask = hostBits > 0 ? (1n << BigInt(hostBits)) - 1n : 0n;
|
|
61
|
+
parsed.start = number & ~mask;
|
|
62
|
+
parsed.end = number | mask;
|
|
63
|
+
return parsed;
|
|
57
64
|
}
|
|
58
65
|
function parseCidrLean(str) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const hostBits = numBits - prefixNum;
|
|
82
|
-
const mask = hostBits > 0 ? (1n << BigInt(hostBits)) - 1n : 0n;
|
|
83
|
-
return {
|
|
84
|
-
start: number & ~mask,
|
|
85
|
-
end: number | mask,
|
|
86
|
-
version
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
function excludeNetsParts(a, b) {
|
|
90
|
-
if (a.start > b.end || a.end < b.start) {
|
|
91
|
-
return [a];
|
|
92
|
-
}
|
|
93
|
-
if (a.start === b.start && a.end === b.end) {
|
|
94
|
-
return [];
|
|
95
|
-
}
|
|
96
|
-
if (a.start > b.start && a.end < b.end) {
|
|
97
|
-
return [];
|
|
98
|
-
}
|
|
99
|
-
const parts = [];
|
|
100
|
-
if (a.start < b.start && a.end <= b.end) {
|
|
101
|
-
parts.push({ start: a.start, end: b.start - 1n });
|
|
102
|
-
}
|
|
103
|
-
if (a.start >= b.start && a.end > b.end) {
|
|
104
|
-
parts.push({ start: b.end + 1n, end: a.end });
|
|
105
|
-
}
|
|
106
|
-
if (a.start < b.start && a.end > b.end) {
|
|
107
|
-
parts.push(
|
|
108
|
-
{ start: a.start, end: b.start - 1n },
|
|
109
|
-
{ start: b.end + 1n, end: a.end }
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
const remaining = [];
|
|
113
|
-
for (const part of parts) {
|
|
114
|
-
subparts(part, remaining);
|
|
115
|
-
}
|
|
116
|
-
return remaining;
|
|
66
|
+
const slashIndex = str.indexOf("/");
|
|
67
|
+
let ipPart;
|
|
68
|
+
let prefixNum;
|
|
69
|
+
if (slashIndex !== -1) {
|
|
70
|
+
ipPart = str.substring(0, slashIndex);
|
|
71
|
+
const prefixStr = str.substring(slashIndex + 1);
|
|
72
|
+
if (!/^[0-9]+$/.test(prefixStr)) throw new Error(`Network is not a CIDR or IP: "${str}"`);
|
|
73
|
+
prefixNum = Number(prefixStr);
|
|
74
|
+
} else {
|
|
75
|
+
ipPart = str;
|
|
76
|
+
prefixNum = -1;
|
|
77
|
+
}
|
|
78
|
+
const { number, version } = parseIp(ipPart);
|
|
79
|
+
if (!version) throw new Error(`Network is not a CIDR or IP: "${str}"`);
|
|
80
|
+
if (prefixNum === -1) prefixNum = bits[version];
|
|
81
|
+
const hostBits = bits[version] - prefixNum;
|
|
82
|
+
const mask = hostBits > 0 ? (1n << BigInt(hostBits)) - 1n : 0n;
|
|
83
|
+
return {
|
|
84
|
+
start: number & ~mask,
|
|
85
|
+
end: number | mask,
|
|
86
|
+
version
|
|
87
|
+
};
|
|
117
88
|
}
|
|
118
89
|
function biggestPowerOfTwo(num) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
let n = num >> 1n;
|
|
122
|
-
while (n > 0n) {
|
|
123
|
-
b++;
|
|
124
|
-
n >>= 1n;
|
|
125
|
-
}
|
|
126
|
-
return 1n << b;
|
|
90
|
+
if (num === 0n) return 0n;
|
|
91
|
+
return 1n << BigInt(num.toString(2).length - 1);
|
|
127
92
|
}
|
|
128
93
|
function subparts(part, output) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
94
|
+
if (!output) output = [];
|
|
95
|
+
if (part.end < part.start) return output;
|
|
96
|
+
if (part.end === part.start) {
|
|
97
|
+
output.push(part);
|
|
98
|
+
return output;
|
|
99
|
+
}
|
|
100
|
+
if (part.end - part.start === 1n) {
|
|
101
|
+
if (part.end % 2n === 0n) output.push({
|
|
102
|
+
start: part.start,
|
|
103
|
+
end: part.start
|
|
104
|
+
}, {
|
|
105
|
+
start: part.end,
|
|
106
|
+
end: part.end
|
|
107
|
+
});
|
|
108
|
+
else output.push({
|
|
109
|
+
start: part.start,
|
|
110
|
+
end: part.end
|
|
111
|
+
});
|
|
112
|
+
return output;
|
|
113
|
+
}
|
|
114
|
+
const size = diff(part.end, part.start);
|
|
115
|
+
let biggest = biggestPowerOfTwo(size);
|
|
116
|
+
let start;
|
|
117
|
+
let end;
|
|
118
|
+
if (size === biggest && part.start % biggest === 0n) {
|
|
119
|
+
output.push(part);
|
|
120
|
+
return output;
|
|
121
|
+
} else if (part.start % biggest === 0n) {
|
|
122
|
+
start = part.start;
|
|
123
|
+
end = start + biggest - 1n;
|
|
124
|
+
} else {
|
|
125
|
+
start = part.end / biggest * biggest;
|
|
126
|
+
if (start + biggest - 1n > part.end) {
|
|
127
|
+
start = (part.end / biggest - 1n) * biggest;
|
|
128
|
+
while (start < part.start) {
|
|
129
|
+
biggest /= 2n;
|
|
130
|
+
start = (part.end / biggest - 1n) * biggest;
|
|
131
|
+
}
|
|
132
|
+
end = start + biggest - 1n;
|
|
133
|
+
} else {
|
|
134
|
+
start = part.end / biggest * biggest;
|
|
135
|
+
end = start + biggest - 1n;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (start !== part.start) subparts({
|
|
139
|
+
start: part.start,
|
|
140
|
+
end: start - 1n
|
|
141
|
+
}, output);
|
|
142
|
+
output.push({
|
|
143
|
+
start,
|
|
144
|
+
end
|
|
145
|
+
});
|
|
146
|
+
if (end !== part.end) subparts({
|
|
147
|
+
start: end + 1n,
|
|
148
|
+
end: part.end
|
|
149
|
+
}, output);
|
|
150
|
+
return output;
|
|
177
151
|
}
|
|
178
152
|
function diff(a, b) {
|
|
179
|
-
|
|
153
|
+
return a + 1n - b;
|
|
180
154
|
}
|
|
181
155
|
function formatPart(part, version) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
const prefix = bits[version] - hostBits;
|
|
191
|
-
return `${ip}/${prefix}`;
|
|
156
|
+
const ip = stringifyIp({
|
|
157
|
+
number: part.start,
|
|
158
|
+
version
|
|
159
|
+
});
|
|
160
|
+
const size = diff(part.end, part.start);
|
|
161
|
+
const hostBits = size <= 1n ? 0 : size.toString(2).length - 1;
|
|
162
|
+
return `${ip}/${bits[version] - hostBits}`;
|
|
192
163
|
}
|
|
193
|
-
function
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
164
|
+
function mergeIntervalsRaw(nets) {
|
|
165
|
+
if (nets.length === 0) return [];
|
|
166
|
+
const sorted = nets.slice().sort((a, b) => a.start > b.start ? 1 : a.start < b.start ? -1 : a.end > b.end ? 1 : a.end < b.end ? -1 : 0);
|
|
167
|
+
const merged = [];
|
|
168
|
+
let curStart = sorted[0].start;
|
|
169
|
+
let curEnd = sorted[0].end;
|
|
170
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
171
|
+
const { start, end } = sorted[i];
|
|
172
|
+
if (start <= curEnd + 1n) {
|
|
173
|
+
if (end > curEnd) curEnd = end;
|
|
174
|
+
} else {
|
|
175
|
+
merged.push({
|
|
176
|
+
start: curStart,
|
|
177
|
+
end: curEnd
|
|
178
|
+
});
|
|
179
|
+
curStart = start;
|
|
180
|
+
curEnd = end;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
merged.push({
|
|
184
|
+
start: curStart,
|
|
185
|
+
end: curEnd
|
|
186
|
+
});
|
|
187
|
+
return merged;
|
|
210
188
|
}
|
|
211
|
-
function
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
let depth = 0;
|
|
216
|
-
const merged = [];
|
|
217
|
-
for (const [index2, number] of numbers.entries()) {
|
|
218
|
-
const marker = maps.get(number);
|
|
219
|
-
if (start === null && marker.start) start = number;
|
|
220
|
-
if (marker.end) end = number;
|
|
221
|
-
if (start === null) continue;
|
|
222
|
-
if (marker.start) depth += marker.start;
|
|
223
|
-
if (marker.end) depth -= marker.end;
|
|
224
|
-
const next = numbers[index2 + 1];
|
|
225
|
-
if (marker.end && depth === 0 && next !== void 0 && next - number > 1n) {
|
|
226
|
-
subparts({ start, end }, merged);
|
|
227
|
-
start = null;
|
|
228
|
-
end = null;
|
|
229
|
-
} else if (index2 === numbers.length - 1) {
|
|
230
|
-
subparts({ start, end }, merged);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
return merged;
|
|
189
|
+
function mergeIntervals(nets) {
|
|
190
|
+
const merged = [];
|
|
191
|
+
for (const part of mergeIntervalsRaw(nets)) subparts(part, merged);
|
|
192
|
+
return merged;
|
|
234
193
|
}
|
|
194
|
+
function subtractSorted(bases, excls) {
|
|
195
|
+
if (excls.length === 0) return bases;
|
|
196
|
+
if (bases.length === 0) return [];
|
|
197
|
+
const result = [];
|
|
198
|
+
let j = 0;
|
|
199
|
+
for (const base of bases) {
|
|
200
|
+
let start = base.start;
|
|
201
|
+
const end = base.end;
|
|
202
|
+
while (j < excls.length && excls[j].end < start) j++;
|
|
203
|
+
let k = j;
|
|
204
|
+
while (k < excls.length && excls[k].start <= end && start <= end) {
|
|
205
|
+
if (excls[k].start > start) result.push({
|
|
206
|
+
start,
|
|
207
|
+
end: excls[k].start - 1n
|
|
208
|
+
});
|
|
209
|
+
start = excls[k].end + 1n;
|
|
210
|
+
k++;
|
|
211
|
+
}
|
|
212
|
+
if (start <= end) result.push({
|
|
213
|
+
start,
|
|
214
|
+
end
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
return result;
|
|
218
|
+
}
|
|
219
|
+
/** Returns an array of merged networks */
|
|
235
220
|
function mergeCidr(nets) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
221
|
+
const arr = uniq(Array.isArray(nets) ? nets : [nets]).map(parseCidrLean);
|
|
222
|
+
const byVersion = {
|
|
223
|
+
4: [],
|
|
224
|
+
6: []
|
|
225
|
+
};
|
|
226
|
+
for (const n of arr) byVersion[n.version].push(n);
|
|
227
|
+
const merged = [];
|
|
228
|
+
for (const v of [4, 6]) for (const part of mergeIntervals(byVersion[v])) merged.push(formatPart(part, v));
|
|
229
|
+
return merged;
|
|
245
230
|
}
|
|
231
|
+
/** Returns an array of merged remaining networks of the subtraction of `excludeNetworks` from `baseNetworks`. */
|
|
246
232
|
function excludeCidr(base, excl) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
const result = [];
|
|
269
|
-
for (const v of [4, 6]) {
|
|
270
|
-
for (const part of bases[v]) {
|
|
271
|
-
result.push(formatPart(part, v));
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
return result;
|
|
233
|
+
const baseArr = uniq(Array.isArray(base) ? base : [base]).map(parseCidrLean);
|
|
234
|
+
const exclArr = uniq(Array.isArray(excl) ? excl : [excl]).map(parseCidrLean);
|
|
235
|
+
const baseByVersion = {
|
|
236
|
+
4: [],
|
|
237
|
+
6: []
|
|
238
|
+
};
|
|
239
|
+
const exclByVersion = {
|
|
240
|
+
4: [],
|
|
241
|
+
6: []
|
|
242
|
+
};
|
|
243
|
+
for (const n of baseArr) baseByVersion[n.version].push(n);
|
|
244
|
+
for (const n of exclArr) exclByVersion[n.version].push(n);
|
|
245
|
+
const result = [];
|
|
246
|
+
for (const v of [4, 6]) {
|
|
247
|
+
const remaining = subtractSorted(mergeIntervalsRaw(baseByVersion[v]), mergeIntervalsRaw(exclByVersion[v]));
|
|
248
|
+
for (const part of remaining) {
|
|
249
|
+
const aligned = subparts(part);
|
|
250
|
+
for (const p of aligned) result.push(formatPart(p, v));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return result;
|
|
275
254
|
}
|
|
276
255
|
function* expandCidr(nets) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
256
|
+
const arr = uniq(Array.isArray(nets) ? nets : [nets]);
|
|
257
|
+
for (const net of mergeCidr(arr)) {
|
|
258
|
+
const { start, end, version } = parseCidrLean(net);
|
|
259
|
+
for (let number = start; number <= end; number++) yield normalizeIp(stringifyIp({
|
|
260
|
+
number,
|
|
261
|
+
version
|
|
262
|
+
}));
|
|
263
|
+
}
|
|
284
264
|
}
|
|
265
|
+
/** Returns a boolean that indicates if `networksA` overlap (intersect) with `networksB`. */
|
|
285
266
|
function overlapCidr(a, b) {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
267
|
+
const aNets = uniq(Array.isArray(a) ? a : [a]).map(parseCidrLean);
|
|
268
|
+
const bNets = uniq(Array.isArray(b) ? b : [b]).map(parseCidrLean);
|
|
269
|
+
const aByVersion = {
|
|
270
|
+
4: [],
|
|
271
|
+
6: []
|
|
272
|
+
};
|
|
273
|
+
const bByVersion = {
|
|
274
|
+
4: [],
|
|
275
|
+
6: []
|
|
276
|
+
};
|
|
277
|
+
for (const n of aNets) aByVersion[n.version].push(n);
|
|
278
|
+
for (const n of bNets) bByVersion[n.version].push(n);
|
|
279
|
+
for (const v of [4, 6]) {
|
|
280
|
+
const aVer = aByVersion[v].sort((x, y) => x.start > y.start ? 1 : x.start < y.start ? -1 : 0);
|
|
281
|
+
const bVer = bByVersion[v].sort((x, y) => x.start > y.start ? 1 : x.start < y.start ? -1 : 0);
|
|
282
|
+
let i = 0, j = 0;
|
|
283
|
+
while (i < aVer.length && j < bVer.length) {
|
|
284
|
+
const aNet = aVer[i];
|
|
285
|
+
const bNet = bVer[j];
|
|
286
|
+
if (aNet.start <= bNet.end && bNet.start <= aNet.end) return true;
|
|
287
|
+
if (aNet.end < bNet.end) i++;
|
|
288
|
+
else j++;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return false;
|
|
305
292
|
}
|
|
293
|
+
/** Returns a boolean that indicates whether `networksA` fully contain all `networksB`. */
|
|
306
294
|
function containsCidr(a, b) {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
return true;
|
|
295
|
+
const aNets = uniq(Array.isArray(a) ? a : [a]).map(parseCidrLean);
|
|
296
|
+
const bNets = uniq(Array.isArray(b) ? b : [b]).map(parseCidrLean);
|
|
297
|
+
const aByVersion = {
|
|
298
|
+
4: [],
|
|
299
|
+
6: []
|
|
300
|
+
};
|
|
301
|
+
const bByVersion = {
|
|
302
|
+
4: [],
|
|
303
|
+
6: []
|
|
304
|
+
};
|
|
305
|
+
for (const n of aNets) aByVersion[n.version].push(n);
|
|
306
|
+
for (const n of bNets) bByVersion[n.version].push(n);
|
|
307
|
+
for (const v of [4, 6]) {
|
|
308
|
+
const containers = aByVersion[v].sort((x, y) => x.start > y.start ? 1 : x.start < y.start ? -1 : 0);
|
|
309
|
+
const targets = bByVersion[v];
|
|
310
|
+
if (targets.length === 0) continue;
|
|
311
|
+
if (containers.length === 0) return false;
|
|
312
|
+
const maxEnd = new Array(containers.length);
|
|
313
|
+
maxEnd[0] = containers[0].end;
|
|
314
|
+
for (let i = 1; i < containers.length; i++) if (containers[i].end > maxEnd[i - 1]) maxEnd[i] = containers[i].end;
|
|
315
|
+
else maxEnd[i] = maxEnd[i - 1];
|
|
316
|
+
for (const target of targets) {
|
|
317
|
+
let lo = 0, hi = containers.length - 1;
|
|
318
|
+
let idx = -1;
|
|
319
|
+
while (lo <= hi) {
|
|
320
|
+
const mid = lo + hi >> 1;
|
|
321
|
+
if (containers[mid].start <= target.start) {
|
|
322
|
+
idx = mid;
|
|
323
|
+
lo = mid + 1;
|
|
324
|
+
} else hi = mid - 1;
|
|
325
|
+
}
|
|
326
|
+
if (idx < 0 || maxEnd[idx] < target.end) return false;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return true;
|
|
343
330
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
};
|
|
353
|
-
export {
|
|
354
|
-
containsCidr,
|
|
355
|
-
index as default,
|
|
356
|
-
excludeCidr,
|
|
357
|
-
expandCidr,
|
|
358
|
-
mergeCidr,
|
|
359
|
-
normalizeCidr,
|
|
360
|
-
overlapCidr,
|
|
361
|
-
parseCidr
|
|
331
|
+
var cidr_tools_default = {
|
|
332
|
+
mergeCidr,
|
|
333
|
+
excludeCidr,
|
|
334
|
+
expandCidr,
|
|
335
|
+
overlapCidr,
|
|
336
|
+
containsCidr,
|
|
337
|
+
normalizeCidr,
|
|
338
|
+
parseCidr
|
|
362
339
|
};
|
|
340
|
+
|
|
341
|
+
//#endregion
|
|
342
|
+
export { containsCidr, cidr_tools_default as default, excludeCidr, expandCidr, mergeCidr, normalizeCidr, overlapCidr, parseCidr };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cidr-tools",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.11",
|
|
4
4
|
"author": "silverwind <me@silverwind.io>",
|
|
5
5
|
"description": "Tools to work with IPv4 and IPv6 CIDR",
|
|
6
6
|
"repository": "silverwind/cidr-tools",
|
|
@@ -17,21 +17,22 @@
|
|
|
17
17
|
"node": ">=18"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"ip-bigint": "^8.2.
|
|
20
|
+
"ip-bigint": "^8.2.7"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@
|
|
24
|
-
"
|
|
25
|
-
"eslint
|
|
23
|
+
"@types/node": "25.3.0",
|
|
24
|
+
"@typescript/native-preview": "7.0.0-dev.20260224.1",
|
|
25
|
+
"eslint": "9.39.3",
|
|
26
|
+
"eslint-config-silverwind": "121.1.3",
|
|
26
27
|
"jest-extended": "7.0.0",
|
|
28
|
+
"tsdown": "0.20.3",
|
|
29
|
+
"tsdown-config-silverwind": "1.7.5",
|
|
27
30
|
"typescript": "5.9.3",
|
|
28
|
-
"typescript-config-silverwind": "
|
|
29
|
-
"updates": "17.
|
|
31
|
+
"typescript-config-silverwind": "15.0.0",
|
|
32
|
+
"updates": "17.6.2",
|
|
30
33
|
"updates-config-silverwind": "1.0.3",
|
|
31
|
-
"versions": "14.
|
|
32
|
-
"vite": "7.3.1",
|
|
33
|
-
"vite-config-silverwind": "6.0.9",
|
|
34
|
+
"versions": "14.2.0",
|
|
34
35
|
"vitest": "4.0.18",
|
|
35
|
-
"vitest-config-silverwind": "10.6.
|
|
36
|
+
"vitest-config-silverwind": "10.6.3"
|
|
36
37
|
}
|
|
37
38
|
}
|