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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/model.mjs +90 -59
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmcf",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
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
- if (data?.name) {
35
- this.name = data.name;
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
- if(this instanceof Host) { return this; }
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
- if(this instanceof Network) { return this; }
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
- owner: this.owner.name
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
- baseDir;
88
- /** @typedef {Map<string,Location>} */ #locations = new Map();
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(baseDir) {
92
- this.baseDir = baseDir;
115
+ constructor(directory) {
116
+ this.directory = directory;
93
117
  }
94
118
 
95
119
  get name() {
96
120
  return "";
97
121
  }
98
122
 
99
- async *locations() {
100
- if (this.#locations.size > 0) {
101
- for (const location of this.#locations.values()) {
102
- yield location;
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
- for await (const name of glob(Location.fileNameGlob, {
107
- cwd: this.baseDir
108
- })) {
109
- yield this.location(name);
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.baseDir
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
- name = Location.baseName(name);
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.baseDir, name);
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(