pmcf 1.27.1 → 1.28.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmcf",
3
- "version": "1.27.1",
3
+ "version": "1.28.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -43,7 +43,7 @@
43
43
  "pacc": "^3.1.9"
44
44
  },
45
45
  "devDependencies": {
46
- "@types/node": "^22.10.10",
46
+ "@types/node": "^22.12.0",
47
47
  "ava": "^6.2.0",
48
48
  "c8": "^10.1.3",
49
49
  "documentation": "^14.0.3",
package/src/base.mjs CHANGED
@@ -43,6 +43,7 @@ export class Base {
43
43
 
44
44
  withOwner(owner) {
45
45
  if (this.owner !== owner) {
46
+ // @ts-ignore
46
47
  return new this.constructor(owner, this);
47
48
  }
48
49
 
@@ -50,6 +51,7 @@ export class Base {
50
51
  }
51
52
 
52
53
  get typeName() {
54
+ // @ts-ignore
53
55
  return this.constructor.typeName;
54
56
  }
55
57
 
@@ -0,0 +1,13 @@
1
+ import { Owner } from "./owner.mjs";
2
+
3
+ export class Cluster extends Owner {
4
+ static get typeName() {
5
+ return "cluster";
6
+ }
7
+
8
+ constructor(owner, data) {
9
+ super(owner, data);
10
+
11
+ owner.addCluster(this);
12
+ }
13
+ }
package/src/model.mjs CHANGED
@@ -2,210 +2,16 @@ import { readFile, glob } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import {
4
4
  asArray,
5
- bridgeToJSON,
6
5
  isIPv4Address,
7
6
  isIPv6Address,
8
7
  normalizeIPAddress
9
8
  } from "./utils.mjs";
10
9
  import { Base } from "./base.mjs";
10
+ import { Owner, Network, Subnet } from "./owner.mjs";
11
11
  import { Service } from "./service.mjs";
12
+ import { Cluster } from "./cluster.mjs";
12
13
  import { DNSService } from "./dns.mjs";
13
14
 
14
- export class Owner extends Base {
15
- #hosts = new Map();
16
- #networks = new Map();
17
- #subnets = new Map();
18
- #bridges = new Set();
19
- #dns;
20
- #administratorEmail;
21
- domain;
22
- ntp = { servers: [] };
23
-
24
- constructor(owner, data) {
25
- super(owner, data);
26
-
27
- let dns;
28
- if (data?.dns) {
29
- dns = data.dns;
30
- delete data.dns;
31
- }
32
-
33
- this.#dns = new DNSService(this, dns);
34
-
35
- if (data?.networks) {
36
- const networks = data.networks;
37
- delete data.networks;
38
-
39
- for (const [name, data] of Object.entries(networks)) {
40
- data.name = name;
41
- new Network(this, data);
42
- }
43
- }
44
- Object.assign(this, data);
45
- }
46
-
47
- _traverse(...args) {
48
- if (super._traverse(...args)) {
49
- for (const network of this.#networks.values()) {
50
- network._traverse(...args);
51
- }
52
-
53
- for (const host of this.#hosts.values()) {
54
- host._traverse(...args);
55
- }
56
-
57
- return true;
58
- }
59
-
60
- return false;
61
- }
62
-
63
- get dns() {
64
- return this.#dns;
65
- }
66
-
67
- async *hosts() {
68
- for (const host of this.#hosts.values()) {
69
- yield host;
70
- }
71
- }
72
-
73
- addObject(object) {
74
- this.world.addObject(object);
75
- }
76
-
77
- addHost(host) {
78
- this.#hosts.set(host.name, host);
79
- this.addObject(host);
80
- }
81
-
82
- async service(filter) {
83
- let best;
84
- for await (const service of this.services(filter)) {
85
- if (!best || service.priority < best.priority) {
86
- best = service;
87
- }
88
- }
89
-
90
- return best;
91
- }
92
-
93
- async *services(filter) {
94
- for await (const host of this.hosts()) {
95
- for await (const service of host.services(filter)) {
96
- yield service;
97
- }
98
- }
99
- }
100
-
101
- networkNamed(name) {
102
- return this.#networks.get(name);
103
- }
104
-
105
- async *networks() {
106
- for (const network of this.#networks.values()) {
107
- yield network;
108
- }
109
- }
110
-
111
- addNetwork(network) {
112
- this.#networks.set(network.fullName, network);
113
- }
114
-
115
- addBridge(network, destinationNetworks) {
116
- if (destinationNetworks) {
117
- let bridge;
118
-
119
- for (bridge of this.#bridges) {
120
- if (bridge.has(network.name)) {
121
- bridge.delete(network.name);
122
- bridge.add(network);
123
- break;
124
- }
125
-
126
- if (bridge.has(network)) {
127
- break;
128
- }
129
- }
130
-
131
- if (!bridge) {
132
- bridge = new Set([network]);
133
- this.#bridges.add(bridge);
134
- }
135
-
136
- for (const name of asArray(destinationNetworks)) {
137
- const other = this.networkNamed(name);
138
- if (other) {
139
- bridge.add(other);
140
- other.bridge = bridge;
141
- } else {
142
- bridge.add(name);
143
- this.finalize(() => this._resolveBridges());
144
- }
145
- }
146
-
147
- return bridge;
148
- }
149
- }
150
-
151
- _resolveBridges() {
152
- for (const bridge of this.#bridges) {
153
- this.info(bridgeToJSON(bridge));
154
- for (const network of bridge) {
155
- if (typeof network === "string") {
156
- const other = this.networkNamed(network);
157
-
158
- if (other) {
159
- bridge.delete(network);
160
- bridge.add(other);
161
- other.bridge = bridge;
162
- } else {
163
- this.error(`Unresolvabale bridge network`, network);
164
- }
165
- }
166
- }
167
- }
168
- }
169
-
170
- async *networkAddresses() {
171
- for await (const host of this.hosts()) {
172
- for (const networkAddresses of host.networkAddresses()) {
173
- yield networkAddresses;
174
- }
175
- }
176
- }
177
-
178
- addSubnet(subnet) {
179
- this.#subnets.set(subnet.name, subnet);
180
- }
181
-
182
- subnet(name) {
183
- return this.#subnets.get(name);
184
- }
185
-
186
- subnets() {
187
- return this.#subnets.values();
188
- }
189
-
190
- get administratorEmail() {
191
- return this.#administratorEmail || "admin@" + this.domain;
192
- }
193
-
194
- get propertyNames() {
195
- return [...super.propertyNames, "domain", "administratorEmail", "dns"];
196
- }
197
-
198
- toJSON() {
199
- return {
200
- ...super.toJSON(),
201
- networks: [...this.#networks.keys()].sort(),
202
- subnets: [...this.#subnets.keys()].sort(),
203
- bridges: [...this.#bridges].map(b => bridgeToJSON(b)),
204
- hosts: [...this.#hosts.keys()].sort()
205
- };
206
- }
207
- }
208
-
209
15
  export class World extends Owner {
210
16
  static get types() {
211
17
  return _typesByName;
@@ -363,73 +169,6 @@ export class Location extends Owner {
363
169
  }
364
170
  }
365
171
 
366
- export class Network extends Owner {
367
- kind;
368
- scope;
369
- metric;
370
- ipv4;
371
- subnet;
372
- bridge;
373
-
374
- static get typeName() {
375
- return "network";
376
- }
377
-
378
- constructor(owner, data) {
379
- super(owner, data);
380
-
381
- let bridge;
382
- if (data.bridge) {
383
- bridge = data.bridge;
384
- delete data.bridge;
385
- }
386
-
387
- Object.assign(this, data);
388
-
389
- const subnetAddress = this.subnetAddress;
390
-
391
- if (subnetAddress) {
392
- let subnet = owner.subnet(subnetAddress);
393
- if (!subnet) {
394
- subnet = new Subnet(owner, { name: subnetAddress });
395
- }
396
-
397
- this.subnet = subnet;
398
- subnet.networks.add(this);
399
- }
400
-
401
- owner.addNetwork(this);
402
-
403
- this.bridge = owner.addBridge(this, bridge);
404
- }
405
-
406
- get netmask() {
407
- const m = this.ipv4?.match(/\/(\d+)$/);
408
- if (m) {
409
- return parseInt(m[1]);
410
- }
411
- }
412
-
413
- get subnetAddress() {
414
- if (this.ipv4) {
415
- const [addr, bits] = this.ipv4.split(/\//);
416
- const parts = addr.split(/\./);
417
- return parts.slice(0, bits / 8).join(".");
418
- }
419
- }
420
-
421
- get propertyNames() {
422
- return [
423
- ...super.propertyNames,
424
- "kind",
425
- "ipv4",
426
- "netmask",
427
- "scope",
428
- "metric",
429
- "bridge"
430
- ];
431
- }
432
- }
433
172
 
434
173
  export class Host extends Base {
435
174
  networkInterfaces = {};
@@ -849,25 +588,6 @@ export class NetworkInterface extends Base {
849
588
  }
850
589
  }
851
590
 
852
- export class Subnet extends Base {
853
- networks = new Set();
854
-
855
- static get typeName() {
856
- return "subnet";
857
- }
858
-
859
- constructor(owner, data) {
860
- super(owner, data);
861
-
862
- Object.assign(this, data);
863
-
864
- owner.addSubnet(this);
865
- }
866
-
867
- get address() {
868
- return this.name;
869
- }
870
- }
871
591
 
872
- const _types = [Location, Network, Subnet, Host, Service, DNSService];
592
+ const _types = [Location, Network, Subnet, Host, Cluster, Service, DNSService];
873
593
  const _typesByName = Object.fromEntries(_types.map(t => [t.typeName, t]));
package/src/module.mjs CHANGED
@@ -1,4 +1,6 @@
1
1
  export * from "./base.mjs";
2
2
  export * from "./service.mjs";
3
3
  export * from "./dns.mjs";
4
+ export * from "./cluster.mjs";
5
+ export * from "./owner.mjs";
4
6
  export * from "./model.mjs";
package/src/owner.mjs ADDED
@@ -0,0 +1,298 @@
1
+ import { asArray, bridgeToJSON } from "./utils.mjs";
2
+
3
+ import { Base } from "./base.mjs";
4
+ import { DNSService } from "./dns.mjs";
5
+
6
+ export class Owner extends Base {
7
+ #hosts = new Map();
8
+ #clusters = new Map();
9
+ #networks = new Map();
10
+ #subnets = new Map();
11
+ #bridges = new Set();
12
+ #dns;
13
+ #administratorEmail;
14
+ domain;
15
+ ntp = { servers: [] };
16
+
17
+ constructor(owner, data) {
18
+ super(owner, data);
19
+
20
+ let dns;
21
+ if (data?.dns) {
22
+ dns = data.dns;
23
+ delete data.dns;
24
+ }
25
+
26
+ this.#dns = new DNSService(this, dns);
27
+
28
+ if (data?.networks) {
29
+ const networks = data.networks;
30
+ delete data.networks;
31
+
32
+ for (const [name, data] of Object.entries(networks)) {
33
+ data.name = name;
34
+ new Network(this, data);
35
+ }
36
+ }
37
+ Object.assign(this, data);
38
+ }
39
+
40
+ _traverse(...args) {
41
+ if (super._traverse(...args)) {
42
+ for (const network of this.#networks.values()) {
43
+ network._traverse(...args);
44
+ }
45
+
46
+ for (const host of this.#hosts.values()) {
47
+ host._traverse(...args);
48
+ }
49
+
50
+ for (const cluster of this.#clusters.values()) {
51
+ cluster._traverse(...args);
52
+ }
53
+
54
+ return true;
55
+ }
56
+
57
+ return false;
58
+ }
59
+
60
+ get dns() {
61
+ return this.#dns;
62
+ }
63
+
64
+ async *hosts() {
65
+ for (const host of this.#hosts.values()) {
66
+ yield host;
67
+ }
68
+ }
69
+
70
+ addObject(object) {
71
+ this.world.addObject(object);
72
+ }
73
+
74
+ addHost(host) {
75
+ this.#hosts.set(host.name, host);
76
+ this.addObject(host);
77
+ }
78
+
79
+ addCluster(cluster) {
80
+ this.#clusters.set(cluster.name, cluster);
81
+ this.addObject(cluster);
82
+ }
83
+
84
+ async service(filter) {
85
+ let best;
86
+ for await (const service of this.services(filter)) {
87
+ if (!best || service.priority < best.priority) {
88
+ best = service;
89
+ }
90
+ }
91
+
92
+ return best;
93
+ }
94
+
95
+ async *services(filter) {
96
+ for await (const host of this.hosts()) {
97
+ for await (const service of host.services(filter)) {
98
+ yield service;
99
+ }
100
+ }
101
+ }
102
+
103
+ networkNamed(name) {
104
+ //console.log(this.toString(), name, this.#networks.keys());
105
+ return this.#networks.get(name);
106
+ }
107
+
108
+ async *networks() {
109
+ for (const network of this.#networks.values()) {
110
+ yield network;
111
+ }
112
+ }
113
+
114
+ addNetwork(network) {
115
+ this.#networks.set(network.fullName, network);
116
+ }
117
+
118
+ addBridge(network, destinationNetworks) {
119
+ if (destinationNetworks) {
120
+ let bridge;
121
+
122
+ for (bridge of this.#bridges) {
123
+ if (bridge.has(network.name)) {
124
+ bridge.delete(network.name);
125
+ bridge.add(network);
126
+ break;
127
+ }
128
+
129
+ if (bridge.has(network)) {
130
+ break;
131
+ }
132
+ }
133
+
134
+ if (!bridge) {
135
+ bridge = new Set([network]);
136
+ this.#bridges.add(bridge);
137
+ }
138
+
139
+ for (const name of asArray(destinationNetworks)) {
140
+ const other = this.networkNamed(name);
141
+ if (other) {
142
+ bridge.add(other);
143
+ other.bridge = bridge;
144
+ } else {
145
+ bridge.add(name);
146
+ this.finalize(() => this._resolveBridges());
147
+ }
148
+ }
149
+
150
+ return bridge;
151
+ }
152
+ }
153
+
154
+ _resolveBridges() {
155
+ for (const bridge of this.#bridges) {
156
+ this.info(bridgeToJSON(bridge));
157
+ for (const network of bridge) {
158
+ if (typeof network === "string") {
159
+ const other = this.networkNamed(network);
160
+
161
+ if (other) {
162
+ bridge.delete(network);
163
+ bridge.add(other);
164
+ other.bridge = bridge;
165
+ } else {
166
+ this.error(`Unresolvabale bridge network`, network);
167
+ }
168
+ }
169
+ }
170
+ }
171
+ }
172
+
173
+ async *networkAddresses() {
174
+ for await (const host of this.hosts()) {
175
+ for (const networkAddresses of host.networkAddresses()) {
176
+ yield networkAddresses;
177
+ }
178
+ }
179
+ }
180
+
181
+ addSubnet(subnet) {
182
+ this.#subnets.set(subnet.name, subnet);
183
+ }
184
+
185
+ subnet(name) {
186
+ return this.#subnets.get(name);
187
+ }
188
+
189
+ subnets() {
190
+ return this.#subnets.values();
191
+ }
192
+
193
+ get administratorEmail() {
194
+ return this.#administratorEmail || "admin@" + this.domain;
195
+ }
196
+
197
+ get propertyNames() {
198
+ return [...super.propertyNames, "domain", "administratorEmail", "dns"];
199
+ }
200
+
201
+ toJSON() {
202
+ return {
203
+ ...super.toJSON(),
204
+ networks: [...this.#networks.keys()].sort(),
205
+ subnets: [...this.#subnets.keys()].sort(),
206
+ bridges: [...this.#bridges].map(b => bridgeToJSON(b)),
207
+ hosts: [...this.#hosts.keys()].sort()
208
+ };
209
+ }
210
+ }
211
+
212
+ export class Network extends Owner {
213
+ kind;
214
+ scope;
215
+ metric;
216
+ ipv4;
217
+ subnet;
218
+ bridge;
219
+
220
+ static get typeName() {
221
+ return "network";
222
+ }
223
+
224
+ constructor(owner, data) {
225
+ super(owner, data);
226
+
227
+ let bridge;
228
+ if (data.bridge) {
229
+ bridge = data.bridge;
230
+ delete data.bridge;
231
+ }
232
+
233
+ Object.assign(this, data);
234
+
235
+ const subnetAddress = this.subnetAddress;
236
+
237
+ if (subnetAddress) {
238
+ let subnet = owner.subnet(subnetAddress);
239
+ if (!subnet) {
240
+ subnet = new Subnet(owner, { name: subnetAddress });
241
+ }
242
+
243
+ this.subnet = subnet;
244
+ subnet.networks.add(this);
245
+ }
246
+
247
+ owner.addNetwork(this);
248
+
249
+ this.bridge = owner.addBridge(this, bridge);
250
+ }
251
+
252
+ get netmask() {
253
+ const m = this.ipv4?.match(/\/(\d+)$/);
254
+ if (m) {
255
+ return parseInt(m[1]);
256
+ }
257
+ }
258
+
259
+ get subnetAddress() {
260
+ if (this.ipv4) {
261
+ const [addr, bits] = this.ipv4.split(/\//);
262
+ const parts = addr.split(/\./);
263
+ return parts.slice(0, bits / 8).join(".");
264
+ }
265
+ }
266
+
267
+ get propertyNames() {
268
+ return [
269
+ ...super.propertyNames,
270
+ "kind",
271
+ "ipv4",
272
+ "netmask",
273
+ "scope",
274
+ "metric",
275
+ "bridge"
276
+ ];
277
+ }
278
+ }
279
+
280
+ export class Subnet extends Base {
281
+ networks = new Set();
282
+
283
+ static get typeName() {
284
+ return "subnet";
285
+ }
286
+
287
+ constructor(owner, data) {
288
+ super(owner, data);
289
+
290
+ Object.assign(this, data);
291
+
292
+ owner.addSubnet(this);
293
+ }
294
+
295
+ get address() {
296
+ return this.name;
297
+ }
298
+ }
package/src/service.mjs CHANGED
@@ -71,6 +71,7 @@ export class Service extends Base {
71
71
  if (this.#ipAddresses) {
72
72
  data.ipAddresses = this.#ipAddresses;
73
73
  }
74
+ // @ts-ignore
74
75
  return new this.constructor(owner, data);
75
76
  }
76
77
 
@@ -0,0 +1,3 @@
1
+ export class Cluster extends Owner {
2
+ }
3
+ import { Owner } from "./owner.mjs";
package/types/model.d.mts CHANGED
@@ -1,35 +1,6 @@
1
- export class Owner extends Base {
2
- domain: any;
3
- ntp: {
4
- servers: any[];
5
- };
6
- _traverse(...args: any[]): boolean;
7
- get dns(): DNSService;
8
- hosts(): AsyncGenerator<any, void, unknown>;
9
- addObject(object: any): void;
10
- addHost(host: any): void;
11
- service(filter: any): Promise<any>;
12
- services(filter: any): AsyncGenerator<any, void, unknown>;
13
- networkNamed(name: any): any;
14
- networks(): AsyncGenerator<any, void, unknown>;
15
- addNetwork(network: any): void;
16
- addBridge(network: any, destinationNetworks: any): any;
17
- _resolveBridges(): void;
18
- networkAddresses(): AsyncGenerator<any, void, unknown>;
19
- addSubnet(subnet: any): void;
20
- subnet(name: any): any;
21
- subnets(): MapIterator<any>;
22
- toJSON(): {
23
- networks: any[];
24
- subnets: any[];
25
- bridges: any[][];
26
- hosts: any[];
27
- };
28
- #private;
29
- }
30
1
  export class World extends Owner {
31
2
  static get types(): {
32
- [k: string]: typeof Service | typeof DNSService | typeof Network | typeof Host | typeof Location | typeof Subnet;
3
+ [k: string]: typeof DNSService | typeof Network | typeof Subnet | typeof Cluster | typeof Service | typeof Host;
33
4
  };
34
5
  constructor(directory: any);
35
6
  get fullName(): string;
@@ -45,16 +16,6 @@ export class World extends Owner {
45
16
  export class Location extends Owner {
46
17
  get location(): this;
47
18
  }
48
- export class Network extends Owner {
49
- kind: any;
50
- scope: any;
51
- metric: any;
52
- ipv4: any;
53
- subnet: any;
54
- bridge: any;
55
- get netmask(): number;
56
- get subnetAddress(): any;
57
- }
58
19
  export class Host extends Base {
59
20
  static prepareData(world: any, data: any): Promise<typeof Host>;
60
21
  networkInterfaces: {};
@@ -110,10 +71,10 @@ export class NetworkInterface extends Base {
110
71
  get kind(): any;
111
72
  #private;
112
73
  }
113
- export class Subnet extends Base {
114
- networks: Set<any>;
115
- get address(): any;
116
- }
117
- import { Base } from "./base.mjs";
74
+ import { Owner } from "./owner.mjs";
118
75
  import { DNSService } from "./dns.mjs";
76
+ import { Network } from "./owner.mjs";
77
+ import { Subnet } from "./owner.mjs";
78
+ import { Cluster } from "./cluster.mjs";
119
79
  import { Service } from "./service.mjs";
80
+ import { Base } from "./base.mjs";
@@ -1,4 +1,6 @@
1
1
  export * from "./base.mjs";
2
2
  export * from "./service.mjs";
3
3
  export * from "./dns.mjs";
4
+ export * from "./cluster.mjs";
5
+ export * from "./owner.mjs";
4
6
  export * from "./model.mjs";
@@ -0,0 +1,46 @@
1
+ export class Owner extends Base {
2
+ domain: any;
3
+ ntp: {
4
+ servers: any[];
5
+ };
6
+ _traverse(...args: any[]): boolean;
7
+ get dns(): DNSService;
8
+ hosts(): AsyncGenerator<any, void, unknown>;
9
+ addObject(object: any): void;
10
+ addHost(host: any): void;
11
+ addCluster(cluster: any): void;
12
+ service(filter: any): Promise<any>;
13
+ services(filter: any): AsyncGenerator<any, void, unknown>;
14
+ networkNamed(name: any): any;
15
+ networks(): AsyncGenerator<any, void, unknown>;
16
+ addNetwork(network: any): void;
17
+ addBridge(network: any, destinationNetworks: any): any;
18
+ _resolveBridges(): void;
19
+ networkAddresses(): AsyncGenerator<any, void, unknown>;
20
+ addSubnet(subnet: any): void;
21
+ subnet(name: any): any;
22
+ subnets(): MapIterator<any>;
23
+ toJSON(): {
24
+ networks: any[];
25
+ subnets: any[];
26
+ bridges: any[][];
27
+ hosts: any[];
28
+ };
29
+ #private;
30
+ }
31
+ export class Network extends Owner {
32
+ kind: any;
33
+ scope: any;
34
+ metric: any;
35
+ ipv4: any;
36
+ subnet: any;
37
+ bridge: any;
38
+ get netmask(): number;
39
+ get subnetAddress(): any;
40
+ }
41
+ export class Subnet extends Base {
42
+ networks: Set<any>;
43
+ get address(): any;
44
+ }
45
+ import { Base } from "./base.mjs";
46
+ import { DNSService } from "./dns.mjs";