pmcf 1.33.0 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -78,12 +78,11 @@ async function generateNamedDefs(owner, targetDir) {
78
78
  zones.push(zone);
79
79
 
80
80
  for (const subnet of owner.subnets()) {
81
- if (subnet.address) {
82
- const reverse = reverseAddress(subnet.address);
83
- const reverseArpa = reverseArpaAddress(subnet.address);
81
+ if (subnet.prefix) {
82
+ const reverseArpa = reverseArpaAddress(subnet.prefix);
84
83
  const zone = {
85
84
  id: reverseArpa,
86
- file: `${reverse}.zone`,
85
+ file: `${reverseArpa}.zone`,
87
86
  records: new Set([SOARecord, NSRecord])
88
87
  };
89
88
  zones.push(zone);
@@ -98,15 +97,15 @@ async function generateNamedDefs(owner, targetDir) {
98
97
  networkInterface
99
98
  } of owner.networkAddresses()) {
100
99
  const host = networkInterface.host;
101
- zone.records.add(
102
- createRecord(
103
- host.domainName + ".",
104
- isIPv4Address(address) ? "A " : "AAAA",
105
- normalizeIPAddress(address)
106
- )
107
- );
108
100
 
109
101
  if (!hosts.has(host)) {
102
+ zone.records.add(
103
+ createRecord(
104
+ host.domainName + ".",
105
+ isIPv4Address(address) ? "A " : "AAAA",
106
+ normalizeIPAddress(address)
107
+ )
108
+ );
110
109
  hosts.add(host);
111
110
  for (const service of host.services()) {
112
111
  //console.log(service.name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmcf",
3
- "version": "1.33.0",
3
+ "version": "1.35.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -43,7 +43,7 @@
43
43
  "pacc": "^3.3.0"
44
44
  },
45
45
  "devDependencies": {
46
- "@types/node": "^22.13.0",
46
+ "@types/node": "^22.13.1",
47
47
  "ava": "^6.2.0",
48
48
  "c8": "^10.1.3",
49
49
  "documentation": "^14.0.3",
package/src/model.mjs CHANGED
@@ -342,15 +342,21 @@ export class Host extends Base {
342
342
  *networkAddresses() {
343
343
  for (const networkInterface of Object.values(this.networkInterfaces)) {
344
344
  for (const address of networkInterface.ipAddresses) {
345
- yield { address, networkInterface };
345
+ yield {
346
+ networkInterface,
347
+ address,
348
+ addressWithPrefixLength:
349
+ networkInterface.addressWithPrefixLength(address)
350
+ };
346
351
  }
347
352
  }
348
353
  }
349
354
 
350
355
  get ipAddresses() {
351
- return [...this.networkAddresses()].map(na =>
352
- normalizeIPAddress(na.address)
353
- );
356
+ return [...this.networkAddresses()].map(na => na.address);
357
+ }
358
+ get ipAddressesWithPrefixLength() {
359
+ return [...this.networkAddresses()].map(na => na.addressWithPrefixLength);
354
360
  }
355
361
 
356
362
  get ipAddress() {
@@ -391,7 +397,7 @@ export class NetworkInterface extends Base {
391
397
  return "network_interface";
392
398
  }
393
399
 
394
- #ipAddresses = [];
400
+ #ipAddresses = new Map();
395
401
  #scope;
396
402
  #metric;
397
403
  #ssid;
@@ -404,21 +410,6 @@ export class NetworkInterface extends Base {
404
410
  constructor(owner, data) {
405
411
  super(owner, data);
406
412
 
407
- if (data.ipv4) {
408
- this.#ipAddresses.push(...asArray(data.ipv4));
409
- delete data.ipv4;
410
- }
411
-
412
- if (data.ipv6) {
413
- this.#ipAddresses.push(...asArray(data.ipv6));
414
- delete data.ipv6;
415
- }
416
-
417
- if (data.ipAddresses) {
418
- this.#ipAddresses.push(...asArray(data.ipAddresses));
419
- delete data.ipAddresses;
420
- }
421
-
422
413
  if (data.ssid) {
423
414
  this.#ssid = data.ssid;
424
415
  delete data.ssid;
@@ -462,26 +453,44 @@ export class NetworkInterface extends Base {
462
453
  //this.arpbridge = owner.addARPBridge(this, data.arpbridge);
463
454
  }
464
455
 
456
+ set ipAddresses(value) {
457
+ const networkOwner = this.owner.owner;
458
+ for (const address of asArray(value)) {
459
+ const subnet = networkOwner.createSubnet(address);
460
+ this.#ipAddresses.set(normalizeIPAddress(address), subnet);
461
+ }
462
+ }
463
+
464
+ subnetForAddress(address) {
465
+ return (
466
+ this.network?.subnetForAddress(address) ||
467
+ this.owner.owner.subnetForAddress(address)
468
+ );
469
+ }
470
+
471
+ addressWithPrefixLength(address) {
472
+ return `${address}/${this.subnetForAddress(address)?.prefixLength}`;
473
+ }
474
+
465
475
  get ipAddresses() {
466
- return this.#ipAddresses;
476
+ return this.#ipAddresses.keys();
467
477
  }
468
478
 
469
479
  get ipAddressesWithPrefixLength() {
470
- return this.#ipAddresses.map(a =>
471
- isIPv4Address(a) ? `${a}/${this.prefixLength}` : a
480
+ return [...this.ipAddresses].map(address =>
481
+ this.addressWithPrefixLength(address)
472
482
  );
473
483
  }
474
484
 
475
485
  get ipv4Addresses() {
476
- return this.#ipAddresses.filter(a => isIPv4Address(a));
486
+ return [...this.ipAddresses].filter(a => isIPv4Address(a));
477
487
  }
478
488
 
479
489
  get ipv6Addresses() {
480
- return this.#ipAddresses.filter(a => isIPv6Address(a));
490
+ return [...this.ipAddresses].filter(a => isIPv6Address(a));
481
491
  }
482
492
 
483
- get prefixLength()
484
- {
493
+ get prefixLength() {
485
494
  return this.network?.prefixLength;
486
495
  }
487
496
 
@@ -538,8 +547,8 @@ export class NetworkInterface extends Base {
538
547
  "psk",
539
548
  "scope",
540
549
  "metric",
541
- "ipAddresses",
542
- "kind"
550
+ "kind",
551
+ "ipAddresses"
543
552
  ];
544
553
  }
545
554
  }
package/src/owner.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { asArray } from "./utils.mjs";
1
+ import { asArray, normalizeCIDR } from "./utils.mjs";
2
2
  import { Base } from "./base.mjs";
3
3
  import { DNSService } from "./dns.mjs";
4
4
 
@@ -83,7 +83,7 @@ export class Owner extends Base {
83
83
 
84
84
  typeNamed(typeName, name) {
85
85
  const typeSlot = this.#membersByType.get(typeName);
86
- return typeSlot?.get(name);
86
+ return typeSlot?.get(name) || this.owner?.typeNamed(typeName, name);
87
87
  }
88
88
 
89
89
  *typeList(typeName) {
@@ -160,6 +160,32 @@ export class Owner extends Base {
160
160
  return this.typeList("subnet");
161
161
  }
162
162
 
163
+ subnetForAddress(address) {
164
+ for (const subnet of this.subnets()) {
165
+ if (subnet.matchesAddress(address)) {
166
+ return subnet;
167
+ }
168
+ }
169
+ }
170
+
171
+ createSubnet(address) {
172
+ if (address instanceof Subnet) {
173
+ return address;
174
+ }
175
+
176
+ const { cidr } = normalizeCIDR(address);
177
+
178
+ if (cidr) {
179
+ let subnet = this.subnetNamed(cidr);
180
+
181
+ if (!subnet) {
182
+ subnet = new Subnet(this, { name: cidr });
183
+ }
184
+
185
+ return subnet;
186
+ }
187
+ }
188
+
163
189
  clusterNamed(name) {
164
190
  return this.typeNamed("cluster", name);
165
191
  }
@@ -260,9 +286,8 @@ export class Network extends Owner {
260
286
  kind;
261
287
  scope;
262
288
  metric;
263
- subnet;
264
289
  bridge;
265
- #ipAddresses = [];
290
+ gateway;
266
291
 
267
292
  static get typeName() {
268
293
  return "network";
@@ -271,9 +296,9 @@ export class Network extends Owner {
271
296
  constructor(owner, data) {
272
297
  super(owner, data);
273
298
 
274
- if (data.ipAddresses) {
275
- this.#ipAddresses.push(...asArray(data.ipAddresses));
276
- delete data.ipAddresses;
299
+ if (data.subnets) {
300
+ this.addSubnets(data.subnets);
301
+ delete data.subnets;
277
302
  }
278
303
 
279
304
  let bridge;
@@ -284,20 +309,6 @@ export class Network extends Owner {
284
309
 
285
310
  Object.assign(this, data);
286
311
 
287
- const subnetAddress = this.subnetAddress;
288
-
289
- if (subnetAddress) {
290
- let subnet = owner.subnetNamed(subnetAddress);
291
- if (!subnet) {
292
- subnet = new Subnet(owner, { name: subnetAddress });
293
- }
294
-
295
- this.subnet = subnet;
296
- subnet.networks.add(this);
297
- }
298
-
299
- //owner.addObject(this);
300
-
301
312
  this.bridge = owner.addBridge(this, bridge);
302
313
  }
303
314
 
@@ -308,32 +319,11 @@ export class Network extends Owner {
308
319
  return super.networkNamed(name);
309
320
  }
310
321
 
311
- set ipAddresses(value) {
312
- this.#ipAddresses = asArray(value);
313
- }
314
-
315
- get ipAddresses() {
316
- return this.#ipAddresses;
317
- }
318
-
319
- get prefixLength() {
320
- for (const a of this.#ipAddresses) {
321
- const m = a.match(/\/(\d+)$/);
322
- if (m) {
323
- return parseInt(m[1]);
324
- }
325
- }
326
-
327
- this.error("no prefixLength", this.#ipAddresses);
328
- }
329
-
330
- get subnetAddress() {
331
- for (const a of this.#ipAddresses) {
332
- const [addr, bits] = a.split(/\//);
333
- if (bits) {
334
- const parts = addr.split(/\./);
335
- return parts.slice(0, bits / 8).join(".");
336
- }
322
+ addSubnets(value) {
323
+ for (const address of asArray(value)) {
324
+ const subnet = this.owner.createSubnet(address);
325
+ this.addObject(subnet);
326
+ subnet.networks.add(this);
337
327
  }
338
328
  }
339
329
 
@@ -341,12 +331,10 @@ export class Network extends Owner {
341
331
  return [
342
332
  ...super.propertyNames,
343
333
  "kind",
344
- "ipAddresses",
345
- "subnet",
346
- "prefixLength",
347
334
  "scope",
348
335
  "metric",
349
- "bridge"
336
+ "bridge",
337
+ "gateway"
350
338
  ];
351
339
  }
352
340
  }
@@ -359,6 +347,16 @@ export class Subnet extends Base {
359
347
  }
360
348
 
361
349
  constructor(owner, data) {
350
+ const { cidr } = normalizeCIDR(data.name);
351
+
352
+ if(!cidr) {
353
+ const error = Error(`Invalid address`);
354
+ error.address = data.name;
355
+ throw error;
356
+ }
357
+
358
+ data.name = cidr;
359
+
362
360
  super(owner, data);
363
361
 
364
362
  Object.assign(this, data);
@@ -366,12 +364,28 @@ export class Subnet extends Base {
366
364
  owner.addObject(this);
367
365
  }
368
366
 
367
+ matchesAddress(address) {
368
+ return address.startsWith(this.prefix);
369
+ }
370
+
371
+ get prefix() {
372
+ const [prefix] = this.name.split("/");
373
+ return prefix;
374
+ }
375
+
376
+ get prefixLength() {
377
+ const m = this.name.match(/\/(\d+)$/);
378
+ if (m) {
379
+ return parseInt(m[1]);
380
+ }
381
+ }
382
+
369
383
  get address() {
370
384
  return this.name;
371
385
  }
372
386
 
373
387
  get propertyNames() {
374
- return [...super.propertyNames, "networks"];
388
+ return [...super.propertyNames, "networks", "prefixLength"];
375
389
  }
376
390
 
377
391
  _traverse(...args) {
package/src/utils.mjs CHANGED
@@ -52,3 +52,21 @@ export function normalizeIPAddress(address) {
52
52
  }
53
53
  return parts.map(s => s.padStart(4, "0")).join(":");
54
54
  }
55
+
56
+ export function normalizeCIDR(address) {
57
+ let [prefix, prefixLength] = address.split(/\//);
58
+
59
+ if (prefixLength) {
60
+ if (isIPv4Address(prefix)) {
61
+ const parts = prefix.split(/\./);
62
+ prefix = parts.slice(0, prefixLength / 8).join(".");
63
+ } else {
64
+ prefix = normalizeIPAddress(prefix);
65
+ }
66
+ }
67
+ else {
68
+ return {};
69
+ }
70
+
71
+ return { prefix, prefixLength, cidr: `${prefix}/${prefixLength}` };
72
+ }
package/types/model.d.mts CHANGED
@@ -38,10 +38,12 @@ export class Host extends Base {
38
38
  services(filter: any): Generator<any, void, unknown>;
39
39
  addNetworkInterface(networkInterface: any): void;
40
40
  networkAddresses(): Generator<{
41
- address: any;
42
41
  networkInterface: any;
42
+ address: any;
43
+ addressWithPrefixLength: any;
43
44
  }, void, unknown>;
44
45
  get ipAddresses(): any[];
46
+ get ipAddressesWithPrefixLength(): any[];
45
47
  get ipAddress(): any;
46
48
  publicKey(type?: string): Promise<string>;
47
49
  toJSON(): {
@@ -55,8 +57,11 @@ export class NetworkInterface extends Base {
55
57
  hwaddr: any;
56
58
  set network(networkOrName: any);
57
59
  get network(): any;
58
- get ipAddresses(): any[];
59
- get ipAddressesWithPrefixLength(): any[];
60
+ set ipAddresses(value: MapIterator<any>);
61
+ get ipAddresses(): MapIterator<any>;
62
+ subnetForAddress(address: any): any;
63
+ addressWithPrefixLength(address: any): string;
64
+ get ipAddressesWithPrefixLength(): string[];
60
65
  get ipv4Addresses(): any[];
61
66
  get ipv6Addresses(): any[];
62
67
  get prefixLength(): any;
package/types/owner.d.mts CHANGED
@@ -21,6 +21,8 @@ export class Owner extends Base {
21
21
  networks(): Generator<any, void, unknown>;
22
22
  subnetNamed(name: any): any;
23
23
  subnets(): Generator<any, void, unknown>;
24
+ subnetForAddress(address: any): any;
25
+ createSubnet(address: any): any;
24
26
  clusterNamed(name: any): any;
25
27
  clusters(): Generator<any, void, unknown>;
26
28
  addBridge(network: any, destinationNetworks: any): any;
@@ -34,16 +36,15 @@ export class Network extends Owner {
34
36
  kind: any;
35
37
  scope: any;
36
38
  metric: any;
37
- subnet: any;
38
39
  bridge: any;
39
- set ipAddresses(value: any[]);
40
- get ipAddresses(): any[];
41
- get prefixLength(): number;
42
- get subnetAddress(): any;
43
- #private;
40
+ gateway: any;
41
+ addSubnets(value: any): void;
44
42
  }
45
43
  export class Subnet extends Base {
46
44
  networks: Set<any>;
45
+ matchesAddress(address: any): any;
46
+ get prefix(): any;
47
+ get prefixLength(): number;
47
48
  get address(): any;
48
49
  _traverse(...args: any[]): boolean;
49
50
  }
package/types/utils.d.mts CHANGED
@@ -5,3 +5,12 @@ export function asArray(value: any): any[];
5
5
  export function isIPv4Address(address: any): boolean;
6
6
  export function isIPv6Address(address: any): boolean;
7
7
  export function normalizeIPAddress(address: any): any;
8
+ export function normalizeCIDR(address: any): {
9
+ prefix?: undefined;
10
+ prefixLength?: undefined;
11
+ cidr?: undefined;
12
+ } | {
13
+ prefix: any;
14
+ prefixLength: any;
15
+ cidr: string;
16
+ };