pmcf 1.46.3 → 1.47.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/bin/pmcf-host-defs +3 -3
- package/bin/pmcf-location-defs +2 -2
- package/bin/pmcf-named-defs +2 -2
- package/package.json +3 -3
- package/src/base.mjs +204 -92
- package/src/cluster.mjs +9 -9
- package/src/dns.mjs +34 -22
- package/src/host.mjs +162 -193
- package/src/location.mjs +19 -19
- package/src/network-support.mjs +9 -0
- package/src/network.mjs +19 -34
- package/src/owner.mjs +66 -69
- package/src/root.mjs +45 -51
- package/src/service.mjs +53 -50
- package/src/subnet.mjs +18 -16
- package/src/types.mjs +40 -14
- package/types/base.d.mts +21 -7
- package/types/cluster.d.mts +277 -2
- package/types/dns.d.mts +15 -2
- package/types/host.d.mts +191 -25
- package/types/location.d.mts +276 -22
- package/types/network-support.d.mts +55 -0
- package/types/network.d.mts +170 -15
- package/types/owner.d.mts +115 -13
- package/types/root.d.mts +294 -1
- package/types/service.d.mts +58 -4
- package/types/subnet.d.mts +11 -2
- package/types/types.d.mts +3 -2
package/src/owner.mjs
CHANGED
|
@@ -4,53 +4,47 @@ import { Subnet } from "./subnet.mjs";
|
|
|
4
4
|
import { addType } from "./types.mjs";
|
|
5
5
|
import { DNSService } from "./dns.mjs";
|
|
6
6
|
|
|
7
|
+
const OwnerTypeDefinition = {
|
|
8
|
+
name: "owner",
|
|
9
|
+
owners: ["owner", "root"],
|
|
10
|
+
priority: 0.9,
|
|
11
|
+
extends: Base.typeDefinition,
|
|
12
|
+
properties: {
|
|
13
|
+
networks: { type: "network", collection: true, writeable: true },
|
|
14
|
+
hosts: { type: "host", collection: true, writeable: true },
|
|
15
|
+
clusters: { type: "cluster", collection: true, writeable: true },
|
|
16
|
+
subnets: { type: Subnet.typeDefinition, collection: true, writeable: true },
|
|
17
|
+
dns: {
|
|
18
|
+
type: DNSService.typeDefinition,
|
|
19
|
+
collection: false,
|
|
20
|
+
writeable: true
|
|
21
|
+
},
|
|
22
|
+
ntp: { type: "string", collection: false, writeable: true },
|
|
23
|
+
domain: { type: "string", collection: false, writeable: true },
|
|
24
|
+
administratorEmail: { type: "string", collection: false, writeable: true }
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const EMPTY = new Map();
|
|
29
|
+
|
|
7
30
|
export class Owner extends Base {
|
|
8
31
|
#membersByType = new Map();
|
|
9
32
|
#bridges = new Set();
|
|
10
33
|
#administratorEmail;
|
|
11
34
|
domain;
|
|
12
|
-
ntp
|
|
35
|
+
ntp;
|
|
13
36
|
|
|
14
37
|
static {
|
|
15
38
|
addType(this);
|
|
16
39
|
}
|
|
17
40
|
|
|
18
41
|
static get typeDefinition() {
|
|
19
|
-
return
|
|
20
|
-
name: "owner",
|
|
21
|
-
extends: Base,
|
|
22
|
-
properties: {
|
|
23
|
-
networks: { type: "network", collection: true },
|
|
24
|
-
hosts: { type: "host", collection: true },
|
|
25
|
-
clusters: { type: "cluster", collection: true },
|
|
26
|
-
subnets: { type: Subnet, collection: true },
|
|
27
|
-
dns: { type: DNSService, collection: false },
|
|
28
|
-
domain: { type: "string" },
|
|
29
|
-
administratorEmail: { type: "string" }
|
|
30
|
-
}
|
|
31
|
-
};
|
|
42
|
+
return OwnerTypeDefinition;
|
|
32
43
|
}
|
|
33
44
|
|
|
34
|
-
constructor(owner, data
|
|
45
|
+
constructor(owner, data) {
|
|
35
46
|
super(owner, data);
|
|
36
|
-
|
|
37
|
-
if (data.administratorEmail) {
|
|
38
|
-
this.#administratorEmail = data.administratorEmail;
|
|
39
|
-
delete data.administratorEmail;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (data.domain) {
|
|
43
|
-
this.domain = data.domain;
|
|
44
|
-
delete data.domain;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (data.ntp) {
|
|
48
|
-
this.ntp = data.ntp;
|
|
49
|
-
delete data.ntp;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
this.read(data);
|
|
53
|
-
|
|
47
|
+
this.read(data, OwnerTypeDefinition);
|
|
54
48
|
owner?.addObject(this);
|
|
55
49
|
}
|
|
56
50
|
|
|
@@ -62,6 +56,8 @@ export class Owner extends Base {
|
|
|
62
56
|
}
|
|
63
57
|
}
|
|
64
58
|
|
|
59
|
+
this.dns?._traverse(...args);
|
|
60
|
+
|
|
65
61
|
return true;
|
|
66
62
|
}
|
|
67
63
|
|
|
@@ -69,6 +65,10 @@ export class Owner extends Base {
|
|
|
69
65
|
}
|
|
70
66
|
|
|
71
67
|
named(name) {
|
|
68
|
+
if (name[0] === "/") {
|
|
69
|
+
name = name.substring(this.fullName.length + 1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
72
|
for (const slot of this.#membersByType.values()) {
|
|
73
73
|
const object = slot.get(name);
|
|
74
74
|
if (object) {
|
|
@@ -78,6 +78,10 @@ export class Owner extends Base {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
typeNamed(typeName, name) {
|
|
81
|
+
if (name[0] === "/") {
|
|
82
|
+
name = name.substring(this.fullName.length + 1);
|
|
83
|
+
}
|
|
84
|
+
|
|
81
85
|
const typeSlot = this.#membersByType.get(typeName);
|
|
82
86
|
return typeSlot?.get(name) || this.owner?.typeNamed(typeName, name);
|
|
83
87
|
}
|
|
@@ -88,29 +92,26 @@ export class Owner extends Base {
|
|
|
88
92
|
|
|
89
93
|
typeList(typeName) {
|
|
90
94
|
const typeSlot = this.#membersByType.get(typeName);
|
|
91
|
-
|
|
92
|
-
return typeSlot.values();
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return [];
|
|
95
|
+
return (typeSlot || EMPTY).values();
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
addTypeObject(typeName, name, object) {
|
|
99
99
|
let typeSlot = this.#membersByType.get(typeName);
|
|
100
100
|
if (!typeSlot) {
|
|
101
101
|
typeSlot = new Map();
|
|
102
102
|
this.#membersByType.set(typeName, typeSlot);
|
|
103
103
|
}
|
|
104
|
-
|
|
104
|
+
|
|
105
|
+
typeSlot.set(name, object);
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
addObject(object) {
|
|
108
|
-
this.
|
|
109
|
+
this.addTypeObject(object.typeName, object.name, object);
|
|
109
110
|
}
|
|
110
111
|
|
|
111
|
-
|
|
112
|
+
findService(filter) {
|
|
112
113
|
let best;
|
|
113
|
-
for (const service of this.
|
|
114
|
+
for (const service of this.findServices(filter)) {
|
|
114
115
|
if (!best || service.priority < best.priority) {
|
|
115
116
|
best = service;
|
|
116
117
|
}
|
|
@@ -119,9 +120,9 @@ export class Owner extends Base {
|
|
|
119
120
|
return best;
|
|
120
121
|
}
|
|
121
122
|
|
|
122
|
-
*
|
|
123
|
+
*findServices(filter) {
|
|
123
124
|
for (const host of this.hosts()) {
|
|
124
|
-
for (const service of host.
|
|
125
|
+
for (const service of host.findServices(filter)) {
|
|
125
126
|
yield service;
|
|
126
127
|
}
|
|
127
128
|
}
|
|
@@ -169,17 +170,14 @@ export class Owner extends Base {
|
|
|
169
170
|
return this.subnetNamed(cidr) || new Subnet(this, cidr);
|
|
170
171
|
}
|
|
171
172
|
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
173
|
+
const subnet = this.subnetForAddress(address);
|
|
174
|
+
if (!subnet) {
|
|
175
|
+
this.error(
|
|
176
|
+
`Address without subnet ${address}`,
|
|
177
|
+
[...this.subnets()].map(s => s.address)
|
|
178
|
+
);
|
|
177
179
|
}
|
|
178
|
-
|
|
179
|
-
this.error(
|
|
180
|
-
`Address without subnet ${address}`,
|
|
181
|
-
[...this.subnets()].map(s => s.address)
|
|
182
|
-
);
|
|
180
|
+
return subnet;
|
|
183
181
|
}
|
|
184
182
|
|
|
185
183
|
subnetForAddress(address) {
|
|
@@ -236,8 +234,6 @@ export class Owner extends Base {
|
|
|
236
234
|
|
|
237
235
|
_resolveBridges() {
|
|
238
236
|
for (const bridge of this.#bridges) {
|
|
239
|
-
//this.info(bridgeToJSON(bridge));
|
|
240
|
-
|
|
241
237
|
const subnets = new Map();
|
|
242
238
|
|
|
243
239
|
for (let network of bridge) {
|
|
@@ -253,7 +249,6 @@ export class Owner extends Base {
|
|
|
253
249
|
this.error(`Unresolvabale bridge network`, network);
|
|
254
250
|
}
|
|
255
251
|
}
|
|
256
|
-
|
|
257
252
|
// enshure only one subnet address in the bridge
|
|
258
253
|
for (const subnet of network.subnets()) {
|
|
259
254
|
const present = subnets.get(subnet.address);
|
|
@@ -277,8 +272,20 @@ export class Owner extends Base {
|
|
|
277
272
|
}
|
|
278
273
|
}
|
|
279
274
|
|
|
275
|
+
set administratorEmail(value) {
|
|
276
|
+
this.#administratorEmail = value;
|
|
277
|
+
}
|
|
278
|
+
|
|
280
279
|
get administratorEmail() {
|
|
281
|
-
|
|
280
|
+
if (this.#administratorEmail) {
|
|
281
|
+
return this.#administratorEmail;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (this.owner) {
|
|
285
|
+
return this.owner.administratorEmail;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return "admin@" + this.domain;
|
|
282
289
|
}
|
|
283
290
|
|
|
284
291
|
*domains() {
|
|
@@ -286,14 +293,4 @@ export class Owner extends Base {
|
|
|
286
293
|
yield location.domain;
|
|
287
294
|
}
|
|
288
295
|
}
|
|
289
|
-
|
|
290
|
-
toJSON() {
|
|
291
|
-
const json = super.toJSON();
|
|
292
|
-
|
|
293
|
-
for (const [typeName, slot] of this.#membersByType) {
|
|
294
|
-
json[typeName] = [...slot.keys()].sort();
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
return json;
|
|
298
|
-
}
|
|
299
296
|
}
|
package/src/root.mjs
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { readFile, glob } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { Base } from "./base.mjs";
|
|
4
3
|
import { Location } from "./location.mjs";
|
|
5
|
-
import { addType, types } from "./types.mjs";
|
|
4
|
+
import { addType, types, resolveTypeLinks } from "./types.mjs";
|
|
5
|
+
|
|
6
|
+
const RootTypeDefinition = {
|
|
7
|
+
name: "root",
|
|
8
|
+
owners: [],
|
|
9
|
+
priority: 1000,
|
|
10
|
+
extends: Location.typeDefinition,
|
|
11
|
+
properties: {}
|
|
12
|
+
};
|
|
6
13
|
|
|
7
14
|
export class Root extends Location {
|
|
8
15
|
static {
|
|
@@ -10,15 +17,12 @@ export class Root extends Location {
|
|
|
10
17
|
}
|
|
11
18
|
|
|
12
19
|
static get typeDefinition() {
|
|
13
|
-
return
|
|
14
|
-
name: "root",
|
|
15
|
-
extends: Location,
|
|
16
|
-
properties: {}
|
|
17
|
-
};
|
|
20
|
+
return RootTypeDefinition;
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
constructor(directory) {
|
|
21
|
-
|
|
24
|
+
resolveTypeLinks();
|
|
25
|
+
super(undefined, "");
|
|
22
26
|
this.directory = directory;
|
|
23
27
|
this.addObject(this);
|
|
24
28
|
}
|
|
@@ -31,63 +35,53 @@ export class Root extends Location {
|
|
|
31
35
|
return this;
|
|
32
36
|
}
|
|
33
37
|
|
|
38
|
+
async _load(name, type) {
|
|
39
|
+
const data = JSON.parse(
|
|
40
|
+
await readFile(
|
|
41
|
+
join(this.directory, name, type.clazz.typeFileName),
|
|
42
|
+
"utf8"
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const parentName = name.replace(/\/[^\/]+$/, "");
|
|
47
|
+
const owner = name === parentName ? this.root : await this.load(parentName);
|
|
48
|
+
|
|
49
|
+
const fullName = this.fullName + "/" + name;
|
|
50
|
+
data.name = fullName.substring(owner.fullName.length + 1);
|
|
51
|
+
|
|
52
|
+
const object = new type.clazz(owner, data);
|
|
53
|
+
|
|
54
|
+
this.addTypeObject(type.clazz.typeName, name, object);
|
|
55
|
+
return object;
|
|
56
|
+
}
|
|
57
|
+
|
|
34
58
|
async load(name, options) {
|
|
35
|
-
|
|
36
|
-
|
|
59
|
+
name = name.replace(/\/([^\/]+\.json)?$/, "");
|
|
60
|
+
|
|
61
|
+
const object = this.named(name);
|
|
37
62
|
if (object) {
|
|
38
63
|
return object;
|
|
39
64
|
}
|
|
40
65
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
let path = fullName.split("/");
|
|
44
|
-
path.pop();
|
|
45
|
-
|
|
46
|
-
let data;
|
|
47
|
-
let type = options?.type;
|
|
48
|
-
if (type) {
|
|
49
|
-
data = JSON.parse(
|
|
50
|
-
await readFile(
|
|
51
|
-
join(this.directory, fullName, type.typeFileName),
|
|
52
|
-
"utf8"
|
|
53
|
-
)
|
|
54
|
-
);
|
|
66
|
+
if (options?.type) {
|
|
67
|
+
return this._load(name, options.type);
|
|
55
68
|
} else {
|
|
56
|
-
for (type of types) {
|
|
69
|
+
for (const type of Object.values(types)) {
|
|
57
70
|
try {
|
|
58
|
-
|
|
59
|
-
await readFile(
|
|
60
|
-
join(this.directory, fullName, type.typeFileName),
|
|
61
|
-
"utf8"
|
|
62
|
-
)
|
|
63
|
-
);
|
|
64
|
-
break;
|
|
71
|
+
return await this._load(name, type);
|
|
65
72
|
} catch {}
|
|
66
73
|
}
|
|
67
|
-
|
|
68
|
-
if (!data) {
|
|
69
|
-
return this.load(path.join("/"), options);
|
|
70
|
-
}
|
|
71
74
|
}
|
|
72
75
|
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
const length = owner.fullName.length;
|
|
76
|
-
const n = fullName[length] === "/" ? length + 1 : length;
|
|
77
|
-
data.name = fullName.substring(n);
|
|
78
|
-
|
|
79
|
-
type = await type.prepareData(this, data);
|
|
80
|
-
|
|
81
|
-
object = new type(owner, data);
|
|
82
|
-
|
|
83
|
-
this._addObject(type.typeName, fullName, object);
|
|
84
|
-
|
|
85
|
-
return object;
|
|
76
|
+
const parentName = name.replace(/\/[^\/]$/, "");
|
|
77
|
+
return name === parentName ? this.root : this.load(parentName, options);
|
|
86
78
|
}
|
|
87
79
|
|
|
88
80
|
async loadAll() {
|
|
89
|
-
for (
|
|
90
|
-
|
|
81
|
+
for (const type of Object.values(types).sort(
|
|
82
|
+
(a, b) => b.priority - a.priority
|
|
83
|
+
)) {
|
|
84
|
+
for await (const name of glob(type.clazz.fileNameGlob, {
|
|
91
85
|
cwd: this.directory
|
|
92
86
|
})) {
|
|
93
87
|
await this.load(name, { type });
|
package/src/service.mjs
CHANGED
|
@@ -14,6 +14,24 @@ const ServiceTypes = {
|
|
|
14
14
|
dhcp: {}
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
const ServiceTypeDefinition = {
|
|
18
|
+
name: "service",
|
|
19
|
+
owners: ["host"],
|
|
20
|
+
priority: 0.4,
|
|
21
|
+
extends: Base.typeDefinition,
|
|
22
|
+
properties: {
|
|
23
|
+
ipAddresses: { type: "string", collection: true, writeable: true },
|
|
24
|
+
addresses: { type: "string", collection: true, writeable: true },
|
|
25
|
+
port: { type: "number", collection: false, writeable: true },
|
|
26
|
+
protocol: { type: "string", collection: false, writeable: true },
|
|
27
|
+
alias: { type: "string", collection: false, writeable: true },
|
|
28
|
+
type: { type: "string", collection: false, writeable: true },
|
|
29
|
+
master: { type: "boolean", collection: false, writeable: true },
|
|
30
|
+
priority: { type: "number", collection: false, writeable: true },
|
|
31
|
+
weight: { type: "number", collection: false, writeable: true }
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
17
35
|
export class Service extends Base {
|
|
18
36
|
alias;
|
|
19
37
|
#weight;
|
|
@@ -27,49 +45,13 @@ export class Service extends Base {
|
|
|
27
45
|
}
|
|
28
46
|
|
|
29
47
|
static get typeDefinition() {
|
|
30
|
-
return
|
|
31
|
-
name: "service",
|
|
32
|
-
extends: Base,
|
|
33
|
-
properties: {
|
|
34
|
-
ipAddresses: { type: "string", collection: true },
|
|
35
|
-
addresses: { type: "string", collection: true },
|
|
36
|
-
port: { type: "number" },
|
|
37
|
-
protocol: { type: "string" },
|
|
38
|
-
alias: { type: "string" },
|
|
39
|
-
type: { type: "string" },
|
|
40
|
-
master: { type: "boolean" },
|
|
41
|
-
priority: { type: "number" },
|
|
42
|
-
weight: { type: "number" }
|
|
43
|
-
}
|
|
44
|
-
};
|
|
48
|
+
return ServiceTypeDefinition;
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
constructor(owner, data) {
|
|
48
52
|
super(owner, data);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
delete data.weight;
|
|
52
|
-
}
|
|
53
|
-
if (data.priority !== undefined) {
|
|
54
|
-
this.#priority = data.priority;
|
|
55
|
-
delete data.priority;
|
|
56
|
-
}
|
|
57
|
-
if (data.type) {
|
|
58
|
-
this.#type = data.type;
|
|
59
|
-
delete data.type;
|
|
60
|
-
}
|
|
61
|
-
if (data.port !== undefined) {
|
|
62
|
-
this.#port = data.port;
|
|
63
|
-
delete data.port;
|
|
64
|
-
}
|
|
65
|
-
if (data.ipAddresses) {
|
|
66
|
-
this.#ipAddresses = data.ipAddresses;
|
|
67
|
-
delete data.ipAddresses;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
Object.assign(this, data);
|
|
71
|
-
|
|
72
|
-
owner.addService(this);
|
|
53
|
+
this.read(data, ServiceTypeDefinition);
|
|
54
|
+
// owner.addService(this);
|
|
73
55
|
}
|
|
74
56
|
|
|
75
57
|
forOwner(owner) {
|
|
@@ -90,6 +72,7 @@ export class Service extends Base {
|
|
|
90
72
|
if (this.#ipAddresses) {
|
|
91
73
|
data.ipAddresses = this.#ipAddresses;
|
|
92
74
|
}
|
|
75
|
+
|
|
93
76
|
// @ts-ignore
|
|
94
77
|
return new this.constructor(owner, data);
|
|
95
78
|
}
|
|
@@ -97,15 +80,8 @@ export class Service extends Base {
|
|
|
97
80
|
return this;
|
|
98
81
|
}
|
|
99
82
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
get srvPrefix() {
|
|
105
|
-
const st = ServiceTypes[this.type];
|
|
106
|
-
if (st?.protocol) {
|
|
107
|
-
return `_${this.type}._${st.protocol}`;
|
|
108
|
-
}
|
|
83
|
+
set ipAddresses(value) {
|
|
84
|
+
this.#ipAddresses = value;
|
|
109
85
|
}
|
|
110
86
|
|
|
111
87
|
get ipAddresses() {
|
|
@@ -116,23 +92,50 @@ export class Service extends Base {
|
|
|
116
92
|
return this.ipAddresses.map(a => `${a}:${this.port}`);
|
|
117
93
|
}
|
|
118
94
|
|
|
95
|
+
set port(value) {
|
|
96
|
+
this.#port = value;
|
|
97
|
+
}
|
|
98
|
+
|
|
119
99
|
get port() {
|
|
120
100
|
return this.#port || ServiceTypes[this.type]?.port;
|
|
121
101
|
}
|
|
122
102
|
|
|
103
|
+
set priority(value) {
|
|
104
|
+
this.#priority = value;
|
|
105
|
+
}
|
|
106
|
+
|
|
123
107
|
get priority() {
|
|
124
108
|
return this.#priority || this.owner.priority || 99;
|
|
125
109
|
}
|
|
126
110
|
|
|
111
|
+
set weight(value) {
|
|
112
|
+
this.#weight = value;
|
|
113
|
+
}
|
|
114
|
+
|
|
127
115
|
get weight() {
|
|
128
116
|
return this.#weight || this.owner.weight || 0;
|
|
129
117
|
}
|
|
130
118
|
|
|
131
|
-
|
|
132
|
-
|
|
119
|
+
set type(value) {
|
|
120
|
+
this.#type = value;
|
|
133
121
|
}
|
|
134
122
|
|
|
135
123
|
get type() {
|
|
136
124
|
return this.#type || this.name;
|
|
137
125
|
}
|
|
126
|
+
|
|
127
|
+
get master() {
|
|
128
|
+
return this.owner.master;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
get protocol() {
|
|
132
|
+
return ServiceTypes[this.type]?.protocol;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
get srvPrefix() {
|
|
136
|
+
const st = ServiceTypes[this.type];
|
|
137
|
+
if (st?.protocol) {
|
|
138
|
+
return `_${this.type}._${st.protocol}`;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
138
141
|
}
|
package/src/subnet.mjs
CHANGED
|
@@ -2,6 +2,23 @@ import { normalizeCIDR, isLinkLocal } from "./utils.mjs";
|
|
|
2
2
|
import { Base } from "./base.mjs";
|
|
3
3
|
import { addType } from "./types.mjs";
|
|
4
4
|
|
|
5
|
+
const SubnetTypeDefinition = {
|
|
6
|
+
name: "subnet",
|
|
7
|
+
owners: ["location", "owner", "network", "root"],
|
|
8
|
+
priority: 0.6,
|
|
9
|
+
constructWithIdentifierOnly: true,
|
|
10
|
+
properties: {
|
|
11
|
+
address: {
|
|
12
|
+
type: "string",
|
|
13
|
+
collection: false,
|
|
14
|
+
writeable: false,
|
|
15
|
+
identifier: true
|
|
16
|
+
},
|
|
17
|
+
networks: { type: "network", collection: true, writeable: true },
|
|
18
|
+
prefixLength: { type: "number", collection: false, writeable: false }
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
5
22
|
export class Subnet extends Base {
|
|
6
23
|
networks = new Set();
|
|
7
24
|
|
|
@@ -10,27 +27,12 @@ export class Subnet extends Base {
|
|
|
10
27
|
}
|
|
11
28
|
|
|
12
29
|
static get typeDefinition() {
|
|
13
|
-
return
|
|
14
|
-
name: "subnet",
|
|
15
|
-
properties: {
|
|
16
|
-
address: { type: "string" },
|
|
17
|
-
networks: { type: "network", collection: true },
|
|
18
|
-
prefixLength: { type: "number", writeable: false }
|
|
19
|
-
}
|
|
20
|
-
};
|
|
30
|
+
return SubnetTypeDefinition;
|
|
21
31
|
}
|
|
22
32
|
|
|
23
33
|
constructor(owner, address) {
|
|
24
34
|
const { cidr } = normalizeCIDR(address);
|
|
25
|
-
|
|
26
|
-
if (!cidr) {
|
|
27
|
-
const error = Error(`Invalid address`);
|
|
28
|
-
error.address = address;
|
|
29
|
-
throw error;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
35
|
super(owner, cidr);
|
|
33
|
-
|
|
34
36
|
owner.addObject(this);
|
|
35
37
|
}
|
|
36
38
|
|
package/src/types.mjs
CHANGED
|
@@ -1,24 +1,50 @@
|
|
|
1
|
+
export const types = {};
|
|
2
|
+
|
|
1
3
|
export function addType(clazz) {
|
|
2
|
-
|
|
4
|
+
const type = clazz.typeDefinition;
|
|
5
|
+
|
|
6
|
+
types[type.name] = type;
|
|
7
|
+
|
|
8
|
+
type.clazz = clazz;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const primitives = new Set(["string", "number", "boolean"]);
|
|
3
12
|
|
|
4
|
-
|
|
5
|
-
|
|
13
|
+
export function resolveTypeLinks() {
|
|
14
|
+
for (const type of Object.values(types)) {
|
|
15
|
+
type.owners = type.owners.map(owner =>
|
|
16
|
+
typeof owner === "string" ? types[owner] : owner
|
|
17
|
+
);
|
|
6
18
|
|
|
7
|
-
|
|
19
|
+
for (const [name, property] of Object.entries(type.properties)) {
|
|
20
|
+
property.name = name;
|
|
21
|
+
if (property.identifier) {
|
|
22
|
+
type.identifier = property;
|
|
23
|
+
}
|
|
8
24
|
|
|
9
|
-
for (const type of types) {
|
|
10
|
-
for (const [name, property] of Object.entries(
|
|
11
|
-
type.typeDefinition.properties
|
|
12
|
-
)) {
|
|
13
25
|
if (typeof property.type === "string") {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
26
|
+
if (!primitives.has(property.type)) {
|
|
27
|
+
const type = types[property.type];
|
|
28
|
+
if (type) {
|
|
29
|
+
property.type = type;
|
|
30
|
+
} else {
|
|
31
|
+
console.error(
|
|
32
|
+
"Unknown type",
|
|
33
|
+
property.type,
|
|
34
|
+
type.name,
|
|
35
|
+
property.name
|
|
36
|
+
);
|
|
37
|
+
}
|
|
17
38
|
}
|
|
18
39
|
}
|
|
19
40
|
}
|
|
20
41
|
}
|
|
21
|
-
}
|
|
22
42
|
|
|
23
|
-
|
|
24
|
-
|
|
43
|
+
for (const type of Object.values(types)) {
|
|
44
|
+
if (!type.identifier) {
|
|
45
|
+
if (type.extends?.identifier) {
|
|
46
|
+
type.identifier = type.extends.identifier;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
package/types/base.d.mts
CHANGED
|
@@ -1,37 +1,51 @@
|
|
|
1
|
-
export function extractFrom(object: any, typeDefinition
|
|
1
|
+
export function extractFrom(object: any, typeDefinition?: any): any;
|
|
2
2
|
export class Base {
|
|
3
3
|
static get typeName(): string;
|
|
4
4
|
static get typeDefinition(): {
|
|
5
5
|
name: string;
|
|
6
|
+
owners: any[];
|
|
6
7
|
properties: {
|
|
8
|
+
owner: {
|
|
9
|
+
type: string;
|
|
10
|
+
collection: boolean;
|
|
11
|
+
writeable: boolean;
|
|
12
|
+
};
|
|
7
13
|
type: {
|
|
8
14
|
type: string;
|
|
15
|
+
collection: boolean;
|
|
9
16
|
writeable: boolean;
|
|
10
17
|
};
|
|
11
18
|
name: {
|
|
12
19
|
type: string;
|
|
20
|
+
collection: boolean;
|
|
21
|
+
identifier: boolean;
|
|
22
|
+
writeable: boolean;
|
|
13
23
|
};
|
|
14
24
|
description: {
|
|
15
25
|
type: string;
|
|
26
|
+
collection: boolean;
|
|
27
|
+
writeable: boolean;
|
|
16
28
|
};
|
|
17
29
|
directory: {
|
|
18
30
|
type: string;
|
|
31
|
+
collection: boolean;
|
|
19
32
|
writeable: boolean;
|
|
20
33
|
};
|
|
21
|
-
owner: {};
|
|
22
34
|
};
|
|
23
35
|
};
|
|
24
|
-
static get nameLookupName(): string;
|
|
25
36
|
static get typeFileName(): string;
|
|
26
37
|
static get fileNameGlob(): string;
|
|
27
|
-
static prepareData(root: any, data: any): Promise<typeof Base>;
|
|
28
|
-
static normalizeName(name: any): any;
|
|
29
38
|
constructor(owner: any, data: any);
|
|
30
39
|
owner: any;
|
|
31
|
-
name: any;
|
|
32
40
|
description: any;
|
|
33
|
-
|
|
41
|
+
name: string;
|
|
42
|
+
ownerFor(property: any, data: any): any;
|
|
43
|
+
read(data: any, type: any): void;
|
|
44
|
+
typeNamed(typeName: any, name: any): any;
|
|
45
|
+
addObject(object: any): any;
|
|
34
46
|
forOwner(owner: any): any;
|
|
47
|
+
isNamed(name: any): boolean;
|
|
48
|
+
relativeName(name: any): any;
|
|
35
49
|
get typeName(): any;
|
|
36
50
|
get root(): any;
|
|
37
51
|
get location(): any;
|