pmcf 1.0.1 → 1.1.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 +1 -1
- package/src/model.mjs +90 -59
package/package.json
CHANGED
package/src/model.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { readFile, writeFile, mkdir, glob } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
-
class Base {
|
|
4
|
+
export class Base {
|
|
5
5
|
owner;
|
|
6
6
|
name;
|
|
7
|
+
description;
|
|
7
8
|
|
|
8
9
|
static get typeName() {
|
|
9
10
|
return "base";
|
|
@@ -31,28 +32,44 @@ class Base {
|
|
|
31
32
|
|
|
32
33
|
constructor(owner, data) {
|
|
33
34
|
this.owner = owner;
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
|
|
36
|
+
if (data) {
|
|
37
|
+
if (data.name) {
|
|
38
|
+
this.name = data.name;
|
|
39
|
+
}
|
|
40
|
+
if (data.description) {
|
|
41
|
+
this.description = data.description;
|
|
42
|
+
}
|
|
36
43
|
}
|
|
37
44
|
}
|
|
38
45
|
|
|
39
|
-
get typeName()
|
|
40
|
-
{
|
|
46
|
+
get typeName() {
|
|
41
47
|
return this.constructor.typeName;
|
|
42
48
|
}
|
|
43
49
|
|
|
44
|
-
get host()
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
get host() {
|
|
51
|
+
if (this instanceof Host) {
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
47
54
|
return this.owner.host;
|
|
48
55
|
}
|
|
49
56
|
|
|
50
|
-
get network()
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
get network() {
|
|
58
|
+
if (this instanceof Network) {
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
53
61
|
return this.owner.network;
|
|
54
62
|
}
|
|
55
63
|
|
|
64
|
+
#directory;
|
|
65
|
+
set directory(directory) {
|
|
66
|
+
this.#directory = directory;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get directory() {
|
|
70
|
+
return this.#directory || this.name;
|
|
71
|
+
}
|
|
72
|
+
|
|
56
73
|
expand(object) {
|
|
57
74
|
if (typeof object === "string") {
|
|
58
75
|
return object.replaceAll(/\$\{([^\}]*)\}/g, (match, m1) => {
|
|
@@ -78,35 +95,62 @@ class Base {
|
|
|
78
95
|
toJSON() {
|
|
79
96
|
return {
|
|
80
97
|
name: this.name,
|
|
81
|
-
|
|
98
|
+
directory: this.directory,
|
|
99
|
+
owner: this.owner.name,
|
|
100
|
+
description: this.description
|
|
82
101
|
};
|
|
83
102
|
}
|
|
84
103
|
}
|
|
85
104
|
|
|
86
105
|
export class World {
|
|
87
|
-
|
|
88
|
-
|
|
106
|
+
static get types() {
|
|
107
|
+
return _types;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
directory;
|
|
111
|
+
#byName = new Map();
|
|
112
|
+
|
|
89
113
|
/** @typedef {Map<string,Host>} */ #hosts = new Map();
|
|
90
114
|
|
|
91
|
-
constructor(
|
|
92
|
-
this.
|
|
115
|
+
constructor(directory) {
|
|
116
|
+
this.directory = directory;
|
|
93
117
|
}
|
|
94
118
|
|
|
95
119
|
get name() {
|
|
96
120
|
return "";
|
|
97
121
|
}
|
|
98
122
|
|
|
99
|
-
async
|
|
100
|
-
|
|
101
|
-
for (const
|
|
102
|
-
|
|
123
|
+
async load() {
|
|
124
|
+
for (const type of Object.values(World.types)) {
|
|
125
|
+
for await (const name of glob(type.fileNameGlob, {
|
|
126
|
+
cwd: this.directory
|
|
127
|
+
})) {
|
|
128
|
+
const baseName = type.baseName(name);
|
|
129
|
+
if (!this.#byName.get(baseName)) {
|
|
130
|
+
const data = JSON.parse(
|
|
131
|
+
await readFile(join(this.directory, name), "utf8")
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
data.name = baseName;
|
|
135
|
+
const object = new type(this, data);
|
|
136
|
+
this.#byName.set(data.name, object);
|
|
137
|
+
}
|
|
103
138
|
}
|
|
104
139
|
}
|
|
140
|
+
}
|
|
105
141
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
142
|
+
async named(name) {
|
|
143
|
+
await this.load();
|
|
144
|
+
return this.#byName.get(name);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async *locations() {
|
|
148
|
+
await this.load();
|
|
149
|
+
|
|
150
|
+
for (const object of this.#byName.values()) {
|
|
151
|
+
if (object instanceof Location) {
|
|
152
|
+
yield object;
|
|
153
|
+
}
|
|
110
154
|
}
|
|
111
155
|
}
|
|
112
156
|
|
|
@@ -118,7 +162,7 @@ export class World {
|
|
|
118
162
|
}
|
|
119
163
|
|
|
120
164
|
for await (const name of glob(Host.fileNameGlob, {
|
|
121
|
-
cwd: this.
|
|
165
|
+
cwd: this.directory
|
|
122
166
|
})) {
|
|
123
167
|
yield this.host(name);
|
|
124
168
|
}
|
|
@@ -131,29 +175,7 @@ export class World {
|
|
|
131
175
|
}
|
|
132
176
|
|
|
133
177
|
async location(name) {
|
|
134
|
-
|
|
135
|
-
if (name === undefined) {
|
|
136
|
-
return undefined;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
let location = this.#locations.get(name);
|
|
140
|
-
if (location) {
|
|
141
|
-
return location;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const directory = join(this.baseDir, name);
|
|
145
|
-
try {
|
|
146
|
-
const data = JSON.parse(
|
|
147
|
-
await readFile(join(directory, Location.typeFileName), "utf8")
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
data.directory = directory;
|
|
151
|
-
data.name = name;
|
|
152
|
-
|
|
153
|
-
location = new Location(this, data);
|
|
154
|
-
} catch {} // TODO
|
|
155
|
-
this.#locations.set(name, location);
|
|
156
|
-
return location;
|
|
178
|
+
return this.#byName.get(Location.baseName(name));
|
|
157
179
|
}
|
|
158
180
|
|
|
159
181
|
async host(name) {
|
|
@@ -168,7 +190,7 @@ export class World {
|
|
|
168
190
|
return host;
|
|
169
191
|
}
|
|
170
192
|
|
|
171
|
-
const directory = join(this.
|
|
193
|
+
const directory = join(this.directory, name);
|
|
172
194
|
const data = JSON.parse(
|
|
173
195
|
await readFile(join(directory, Host.typeFileName), "utf8")
|
|
174
196
|
);
|
|
@@ -216,8 +238,7 @@ export class World {
|
|
|
216
238
|
}
|
|
217
239
|
}
|
|
218
240
|
|
|
219
|
-
class Host extends Base {
|
|
220
|
-
directory;
|
|
241
|
+
export class Host extends Base {
|
|
221
242
|
networkInterfaces = {};
|
|
222
243
|
services = {};
|
|
223
244
|
postinstall = [];
|
|
@@ -382,7 +403,6 @@ class Host extends Base {
|
|
|
382
403
|
...super.toJSON(),
|
|
383
404
|
...Object.fromEntries(
|
|
384
405
|
[
|
|
385
|
-
"directory",
|
|
386
406
|
"location",
|
|
387
407
|
"model",
|
|
388
408
|
"os",
|
|
@@ -404,10 +424,9 @@ class Host extends Base {
|
|
|
404
424
|
}
|
|
405
425
|
}
|
|
406
426
|
|
|
407
|
-
class Model extends Host {}
|
|
427
|
+
export class Model extends Host {}
|
|
408
428
|
|
|
409
|
-
class Location extends Base {
|
|
410
|
-
directory;
|
|
429
|
+
export class Location extends Base {
|
|
411
430
|
domain;
|
|
412
431
|
dns;
|
|
413
432
|
#administratorEmail;
|
|
@@ -574,9 +593,11 @@ class Location extends Base {
|
|
|
574
593
|
}
|
|
575
594
|
}
|
|
576
595
|
|
|
577
|
-
class Network extends Base {
|
|
596
|
+
export class Network extends Base {
|
|
578
597
|
#hosts = new Map();
|
|
579
598
|
kind;
|
|
599
|
+
scope;
|
|
600
|
+
metric;
|
|
580
601
|
ipv4;
|
|
581
602
|
ipv4_netmask;
|
|
582
603
|
subnet;
|
|
@@ -619,12 +640,15 @@ class Network extends Base {
|
|
|
619
640
|
toJSON() {
|
|
620
641
|
return {
|
|
621
642
|
...super.toJSON(),
|
|
622
|
-
kind: this.kind
|
|
643
|
+
kind: this.kind,
|
|
644
|
+
ipv4: this.ipv4,
|
|
645
|
+
scope: this.scope,
|
|
646
|
+
metric: this.metric
|
|
623
647
|
};
|
|
624
648
|
}
|
|
625
649
|
}
|
|
626
650
|
|
|
627
|
-
class Subnet extends Base {
|
|
651
|
+
export class Subnet extends Base {
|
|
628
652
|
networks = new Set();
|
|
629
653
|
|
|
630
654
|
static get typeName() {
|
|
@@ -653,7 +677,7 @@ const ServiceTypes = {
|
|
|
653
677
|
dhcp: {}
|
|
654
678
|
};
|
|
655
679
|
|
|
656
|
-
class Service extends Base {
|
|
680
|
+
export class Service extends Base {
|
|
657
681
|
alias;
|
|
658
682
|
#weight;
|
|
659
683
|
#priority;
|
|
@@ -733,6 +757,13 @@ class Service extends Base {
|
|
|
733
757
|
}
|
|
734
758
|
}
|
|
735
759
|
|
|
760
|
+
const _types = Object.fromEntries(
|
|
761
|
+
[Location, Network, Subnet, Host, /*Model,*/ Service].map(t => [
|
|
762
|
+
t.typeName,
|
|
763
|
+
t
|
|
764
|
+
])
|
|
765
|
+
);
|
|
766
|
+
|
|
736
767
|
export async function writeLines(dir, name, lines) {
|
|
737
768
|
await mkdir(dir, { recursive: true });
|
|
738
769
|
return writeFile(
|