pmcf 6.37.2 → 6.38.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": "6.37.2",
3
+ "version": "6.38.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -53,7 +53,7 @@
53
53
  "aggregated-map": "^1.0.10",
54
54
  "content-entry-transform": "^1.7.3",
55
55
  "ip-utilties": "^3.13.0",
56
- "npm-pkgbuild": "^20.9.5",
56
+ "npm-pkgbuild": "^21.0.0",
57
57
  "pacc": "^11.6.0",
58
58
  "package-directory": "^8.2.0",
59
59
  "yaml": "^2.9.0"
package/src/base.mjs CHANGED
@@ -1,20 +1,14 @@
1
1
  import { join } from "node:path";
2
2
  import { stat } from "node:fs/promises";
3
- import { AggregatedMap } from "aggregated-map";
4
- import { allOutputs } from "npm-pkgbuild";
5
3
  import {
6
4
  createExpressionTransformer,
7
5
  transform
8
6
  } from "content-entry-transform";
9
7
  import { FileContentProvider } from "npm-pkgbuild";
10
8
  import {
11
- getAttribute,
12
9
  parse,
13
10
  globals,
14
- expand,
15
11
  extract,
16
- toExternal,
17
- filterPublic,
18
12
  extendingAttributeIterator,
19
13
  name_attribute_writable,
20
14
  type_attribute_writable,
@@ -22,10 +16,10 @@ import {
22
16
  string_set_attribute_writable,
23
17
  description_attribute_writable,
24
18
  boolean_attribute_writable,
25
- object_attribute
19
+ default_attribute_writable
26
20
  } from "pacc";
27
21
  import { union } from "./utils.mjs";
28
- import { addType } from "pmcf";
22
+ import { addType, Core } from "pmcf";
29
23
  import { owner_attribute, aliases_attribute } from "./common-attributes.mjs";
30
24
 
31
25
  /**
@@ -33,7 +27,7 @@ import { owner_attribute, aliases_attribute } from "./common-attributes.mjs";
33
27
  * attributes: as declared in the types
34
28
  * properties: use defined values to support attribute value definitions
35
29
  */
36
- export class Base {
30
+ export class Base extends Core {
37
31
  static name = "base";
38
32
  static key = "name";
39
33
  static priority = 0;
@@ -52,8 +46,7 @@ export class Base {
52
46
  private: true
53
47
  },
54
48
 
55
- packaging: { ...string_set_attribute_writable, name: "packaging" },
56
- // packageContentProperties: { ...object_attribute, writable: true, name: "packageContentProperties"}
49
+ content: { ...default_attribute_writable, type: "content", name: "content" }
57
50
  };
58
51
 
59
52
  static {
@@ -67,94 +60,22 @@ export class Base {
67
60
  description;
68
61
  name;
69
62
  properties = {};
70
- extends = new Set();
71
63
  _aliases = new Set();
72
64
  _tags = new Set();
73
- _packaging = new Set();
74
65
  _directory;
75
66
 
76
- constructor(owner, data) {
77
- if (owner) {
78
- this.owner = owner;
79
- }
80
- }
81
-
82
- set owner(value) {
83
- if (this === value || this === value?.owner) {
84
- this.error("Unable to own myself", value.fullName);
85
- } else {
86
- this._owner = value;
87
- }
88
- }
89
-
90
- get owner() {
91
- return this._owner;
92
- }
93
-
94
- forOwner(owner) {
95
- if (this.owner !== owner) {
96
- const newObject = Object.create(this);
97
- newObject.owner = owner;
98
- return newObject;
99
- }
100
-
101
- return this;
67
+ value(name) {
68
+ return this.attribute(name) ?? this.property(name) ?? this.named(name);
102
69
  }
103
70
 
104
71
  materializeExtends() {
105
- for (const [path, attribute] of extendingAttributeIterator(
106
- this.constructor,
107
- attribute => attribute.collection && !attribute.type.primitive
108
- )) {
109
- if (attribute.deferredExpression) {
110
- const name = attribute.name;
111
- if (!this.hasOwnProperty(name)) {
112
- for (const e of this.walkDirections(["extends"])) {
113
- if (e.hasOwnProperty(name)) {
114
- Object.defineProperty(this, name, {
115
- get: () => e[name]
116
- });
117
- break;
118
- }
119
- }
72
+ super.materializeExtends();
73
+ if (this.content) {
74
+ for (const e of this.extends) {
75
+ if (e.content) {
76
+ this.content.extends.add(e.content);
120
77
  }
121
-
122
- continue;
123
78
  }
124
-
125
- const collection = this[attribute.name];
126
-
127
- if (typeof collection?.get === "function") {
128
- for (const [name, extending] of this.mapFromDirections(
129
- ["extends"],
130
- attribute.name
131
- )) {
132
- const present = collection.get(extending.name);
133
-
134
- if (present) {
135
- present.extends.add(extending);
136
- present.materializeExtends();
137
- } else {
138
- collection.set(extending.name, extending.forOwner(this));
139
- }
140
- }
141
- } /*else {
142
- if (Array.isArray(collection)) {
143
- // TODO
144
- } else {
145
- //console.log("EXTENDS", this.fullName, attribute.name);
146
-
147
- for (const extending of this.unionFromDirections(
148
- ["extends"],
149
- attribute.name
150
- )) {
151
- if (!collection.has(extending)) {
152
- //console.log("ADD", this.fullName, extending.fullName);
153
- collection.add(extending);
154
- }
155
- }
156
- }
157
- }*/
158
79
  }
159
80
  }
160
81
 
@@ -180,184 +101,6 @@ export class Base {
180
101
  }
181
102
  }
182
103
 
183
- /**
184
- * Deliver AggregatedMap of all property Maps.
185
- * @param {string[]} directions
186
- * @param {string} property
187
- * @returns {Map<any,any>}
188
- */
189
- mapFromDirections(directions, property) {
190
- return new AggregatedMap(
191
- [...this.walkDirections(directions)]
192
- .map(node => node[property])
193
- .filter(node => node !== undefined)
194
- );
195
- }
196
-
197
- /**
198
- * Deliver union set of all property values.
199
- * @param {string[]} directions
200
- * @param {string} property
201
- * @returns {Set<any>}
202
- */
203
- unionFromDirections(directions, property) {
204
- let collected = new Set();
205
- for (const node of this.walkDirections(directions)) {
206
- const value = node[property];
207
- if (value !== undefined) {
208
- if (!(value instanceof Set)) {
209
- console.log("NO SET", value, node.fullName, property);
210
- }
211
- collected = collected.union(value);
212
- }
213
- }
214
-
215
- return collected;
216
- }
217
-
218
- get children() {
219
- const all = [];
220
-
221
- for (const [path, attribute] of extendingAttributeIterator(
222
- this.constructor,
223
- attribute => attribute.backpointer?.name === "owner"
224
- )) {
225
- const value = this[path];
226
-
227
- if (value !== undefined) {
228
- if (attribute.collection) {
229
- if (typeof value.values === "function") {
230
- all.push(...value.values());
231
- } else {
232
- if (value instanceof Iterator) {
233
- all.push(...value);
234
- } else {
235
- if (value instanceof Base) {
236
- this.error(
237
- `Unexpected scalar value for "${attribute.name}"`,
238
- value.fullName
239
- );
240
- all.push(value); // TODO should not happen
241
- } else if (typeof value === "object") {
242
- all.push(...Object.values(value));
243
- }
244
- }
245
- }
246
- } else {
247
- all.push(value);
248
- }
249
- }
250
- }
251
-
252
- return all;
253
- }
254
-
255
- /**
256
- * Walk the object graph in some directions and deliver seen nodes.
257
- * @param {string[]} directions
258
- * @return {Iterable<Base>}
259
- */
260
- *walkDirections(directions = ["this", "extends", "owner"]) {
261
- if (directions.indexOf("this") >= 0) {
262
- yield this;
263
- directions = directions.filter(d => d !== "this");
264
- }
265
-
266
- yield* this._walkDirections(directions, new Set());
267
- }
268
-
269
- *_walkDirections(directions, seen) {
270
- if (!seen.has(this)) {
271
- seen.add(this);
272
-
273
- for (const direction of directions) {
274
- const value = this[direction];
275
-
276
- if (value) {
277
- if (value[Symbol.iterator]) {
278
- for (const node of value) {
279
- yield node;
280
- yield* node._walkDirections(directions, seen);
281
- }
282
- } else {
283
- yield value;
284
- yield* value._walkDirections(directions, seen);
285
- }
286
- }
287
- }
288
- }
289
- }
290
-
291
- get typeName() {
292
- return this.constructor.name;
293
- }
294
-
295
- /**
296
- *
297
- * @param {string} name
298
- * @returns {any}
299
- */
300
- attribute(name) {
301
- for (const node of this.walkDirections(["this", "extends"])) {
302
- const value = getAttribute(node, name);
303
- if (value !== undefined) {
304
- return this.expand(value);
305
- }
306
- }
307
- }
308
-
309
- /**
310
- * Retrive attribute values from an object.
311
- * @param {Function} [filter]
312
- * @return {Iterable<[string,any]>} values
313
- */
314
- *attributeIterator(filter) {
315
- for (const [path, attribute] of extendingAttributeIterator(
316
- this.constructor,
317
- filter
318
- )) {
319
- const name = path.join(".");
320
- const value = this.attribute(name);
321
-
322
- if (value !== undefined) {
323
- yield [
324
- attribute.externalName ?? name,
325
- toExternal(value, attribute),
326
- path,
327
- attribute
328
- ];
329
- }
330
- }
331
- }
332
-
333
- /**
334
- * Retrive attribute values from an object.
335
- * @param {Function} [filter]
336
- * @return {Object} values
337
- */
338
- getAttributes(filter = filterPublic) {
339
- return Object.fromEntries(this.attributeIterator(filter));
340
- }
341
-
342
- value(name) {
343
- return this.attribute(name) ?? this.property(name) ?? this.named(name);
344
- }
345
-
346
- /**
347
- *
348
- * @param {string} name
349
- * @returns {any}
350
- */
351
- property(name) {
352
- for (const node of this.walkDirections()) {
353
- const value = node.properties[name];
354
-
355
- if (value !== undefined) {
356
- return this.expand(value);
357
- }
358
- }
359
- }
360
-
361
104
  get root() {
362
105
  return this.owner?.root;
363
106
  }
@@ -442,22 +185,6 @@ export class Base {
442
185
  return this.expression("services[types[smtp]][0]");
443
186
  }
444
187
 
445
- /**
446
- *
447
- * @param {string} expression
448
- * @param {object} options
449
- * @returns {any}
450
- */
451
- expression(expression, options) {
452
- return parse(expression, {
453
- root: this.root,
454
- current: this,
455
- valueFor: (name, at) =>
456
- typeof at?.value === "function" ? at.value(name) : globals[name],
457
- ...options
458
- });
459
- }
460
-
461
188
  get services() {
462
189
  return this.owner?.services || new Map();
463
190
  }
@@ -479,28 +206,6 @@ export class Base {
479
206
  return this.owner ? join(this.owner.fullName, "/", this.name) : this.name;
480
207
  }
481
208
 
482
- get derivedPackaging() {
483
- return this.owner?.packaging;
484
- }
485
-
486
- set packaging(value) {
487
- this._packaging = union(value, this._packaging);
488
- }
489
-
490
- get packaging() {
491
- const dp = this.derivedPackaging;
492
-
493
- if (dp) {
494
- return this._packaging.union(dp);
495
- }
496
-
497
- return this._packaging;
498
- }
499
-
500
- get outputs() {
501
- return new Set(allOutputs.filter(o => this.packaging.has(o.name)));
502
- }
503
-
504
209
  get systemUserName() {
505
210
  return this.constructor.name;
506
211
  }
@@ -509,36 +214,16 @@ export class Base {
509
214
  return this.constructor.name;
510
215
  }
511
216
 
512
- get packageContentPermissions() {
513
- const owner = this.systemUserName;
514
- const group = this.systemGroupName;
515
- return [
516
- {
517
- mode: 0o644,
518
- owner,
519
- group
520
- },
521
- {
522
- mode: 0o755,
523
- owner,
524
- group
525
- }
526
- ];
527
- }
528
-
529
217
  get packageData() {
530
- const nameParts = [this.typeName, this.owner?.name, this.name];
531
- return {
532
- sources: [],
533
- outputs: this.outputs,
534
- properties: {
535
- name: nameParts.filter(n => n !== undefined && n.length > 0).join("-"),
536
- description: `${this.type} definitions for ${this.fullName}`,
537
- access: "private",
538
- dependencies: this.depends,
539
- groups: [this.typeName]
218
+ if (!this.content) {
219
+ for (const e of this.walkDirections(["extends"])) {
220
+ if (e.content) {
221
+ this.content = e.content.forOwner(this);
222
+ break;
223
+ }
540
224
  }
541
- };
225
+ }
226
+ return this.content?.packageData(this);
542
227
  }
543
228
 
544
229
  async *preparePackages(stagingDir) {}
@@ -600,32 +285,12 @@ export class Base {
600
285
  * @return {boolean}
601
286
  */
602
287
  get isTemplate() {
603
- //console.log("T", this.name, this.owner?.name, this.owner?.owner?.name);
604
288
  return (
605
289
  this.template ??
606
290
  (this.name?.indexOf("*") >= 0 || this.owner?.isTemplate || false)
607
291
  );
608
292
  }
609
293
 
610
- /**
611
- *
612
- * @param {any} object
613
- * @returns {any}
614
- */
615
- expand(object) {
616
- if (this.isTemplate || object instanceof Base) {
617
- return object;
618
- }
619
-
620
- return expand(object, {
621
- stopClass: Base,
622
- root: this.root,
623
- current: this,
624
- valueFor: (name, at) =>
625
- typeof at?.value === "function" ? at.value(name) : globals[name]
626
- });
627
- }
628
-
629
294
  error(...args) {
630
295
  console.error(`${this.toString()}:`, ...args);
631
296
  }
package/src/content.mjs CHANGED
@@ -3,18 +3,29 @@ import {
3
3
  string_set_attribute_writable,
4
4
  default_collection_attribute_writable
5
5
  } from "pacc";
6
- import { Base, addType } from "pmcf";
6
+ import { allOutputs } from "npm-pkgbuild";
7
+ import { Core, addType } from "pmcf";
8
+ import { union } from "./utils.mjs";
7
9
 
8
- export class permission extends Base {
10
+ export class permission extends Core {
11
+ static priority = 1.9;
9
12
  static attributes = {
10
13
  pattern: { ...string_attribute_writable, key: true, name: "pattern" },
11
14
  user: { ...string_attribute_writable, name: "user" },
12
15
  group: { ...string_attribute_writable, name: "group" },
13
16
  mode: { ...string_attribute_writable, name: "mode" }
14
17
  };
18
+
19
+ static {
20
+ addType(this);
21
+ }
22
+
23
+ get name() {
24
+ return this.pattern;
25
+ }
15
26
  }
16
27
 
17
- export class content extends Base {
28
+ export class content extends Core {
18
29
  static priority = 1.9;
19
30
  static attributes = {
20
31
  permissions: {
@@ -22,21 +33,75 @@ export class content extends Base {
22
33
  type: permission,
23
34
  name: "permissions"
24
35
  },
36
+ access: {
37
+ ...string_attribute_writable,
38
+ name: "access",
39
+ default: "private"
40
+ },
25
41
  replaces: { ...string_set_attribute_writable, name: "replaces" },
26
42
  depends: { ...string_set_attribute_writable, name: "depends" },
27
43
  provides: { ...string_set_attribute_writable, name: "provides" },
28
- optional: { ...string_set_attribute_writable, name: "optional" }
44
+ optional: { ...string_set_attribute_writable, name: "optional" },
45
+ groups: { ...string_set_attribute_writable, name: "groups" },
46
+ backup: { ...string_set_attribute_writable, name: "backup" },
47
+ packaging: { ...string_set_attribute_writable, name: "packaging" }
29
48
  };
30
49
 
31
50
  static {
32
51
  addType(this);
33
52
  }
34
53
 
35
- permissions = new Map();
54
+ _permissions = new Map();
36
55
  _provides = new Set();
37
56
  _replaces = new Set();
38
57
  _depends = new Set();
39
58
  _optional = new Set();
59
+ _packaging = new Set();
60
+ _groups = new Set();
61
+
62
+ get name() {
63
+ return "content";
64
+ }
65
+
66
+ value(name) {
67
+ // console.log("CONTENT VALUE", this.name, this.owner.fullName, name, this.owner.name);
68
+ return this.owner.value(name) ?? super.value(name);
69
+ }
70
+
71
+ /**
72
+ * @return {string}
73
+ */
74
+ get access() {
75
+ return this.attribute("_access");
76
+ }
77
+
78
+ set access(value) {
79
+ this._access = value;
80
+ }
81
+
82
+ set packaging(value) {
83
+ this._packaging = union(value, this._packaging);
84
+ }
85
+
86
+ get packaging() {
87
+ const dp = this.derivedPackaging;
88
+
89
+ if (dp) {
90
+ return this._packaging.union(dp);
91
+ }
92
+
93
+ return this._packaging;
94
+ }
95
+
96
+ get outputs() {
97
+ return new Set(allOutputs.filter(o => this.packaging.has(o.name)));
98
+ }
99
+
100
+ get derivedPackaging() {
101
+ return this.expand(
102
+ this.unionFromDirections(["this", "extends"], "_packaging")
103
+ );
104
+ }
40
105
 
41
106
  set provides(value) {
42
107
  this._provides = union(value, this._provides);
@@ -77,4 +142,67 @@ export class content extends Base {
77
142
  this.unionFromDirections(["this", "extends"], "_optional")
78
143
  );
79
144
  }
145
+
146
+ set groups(value) {
147
+ this._groups = union(value, this._groups);
148
+ }
149
+
150
+ get groups() {
151
+ return this.expand(
152
+ this.unionFromDirections(["this", "extends"], "_groups")
153
+ );
154
+ }
155
+
156
+ set backup(value) {
157
+ this._backup = union(value, this._backup);
158
+ }
159
+
160
+ get backup() {
161
+ return this.expand(
162
+ this.unionFromDirections(["this", "extends"], "_backup")
163
+ );
164
+ }
165
+
166
+ get permissions() {
167
+ const p = this.mapFromDirections(["this", "extends"], "_permissions");
168
+
169
+ return p;
170
+
171
+ /*
172
+ const owner = this.systemUserName;
173
+ const group = this.systemGroupName;
174
+ return [
175
+ {
176
+ mode: 0o644,
177
+ owner,
178
+ group
179
+ },
180
+ {
181
+ mode: 0o755,
182
+ owner,
183
+ group
184
+ }
185
+ ];
186
+ */
187
+ }
188
+
189
+ packageData(node) {
190
+ const nameParts = [node.typeName, node.owner?.name, node.name];
191
+
192
+ return {
193
+ sources: [],
194
+ outputs: this.outputs,
195
+ properties: {
196
+ name: nameParts.filter(n => n !== undefined && n.length > 0).join("-"),
197
+ description: `${node.type} definitions for ${node.fullName}`,
198
+ access: this.access,
199
+ groups: [node.typeName, ...this.groups],
200
+ depends: [...this.depends],
201
+ provides: [...this.provides],
202
+ replaces: [...this.replaces],
203
+ optional: [...this.optional],
204
+ backup: [...this.backup]
205
+ }
206
+ };
207
+ }
80
208
  }
@@ -282,8 +282,9 @@ export class CoreService extends Base {
282
282
  const pd = this.packageData;
283
283
 
284
284
  pd.sources = await Array.fromAsync(
285
- this.templateContent(...this.packageContentPermissions)
285
+ this.templateContent(this.content.permissions)
286
286
  );
287
+
287
288
  if (pd.sources.length) {
288
289
  yield pd;
289
290
  }
package/src/core.mjs ADDED
@@ -0,0 +1,325 @@
1
+ import { AggregatedMap } from "aggregated-map";
2
+
3
+ import {
4
+ toExternal,
5
+ filterPublic,
6
+ parse,
7
+ extendingAttributeIterator,
8
+ getAttribute,
9
+ expand,
10
+ globals
11
+ } from "pacc";
12
+ import { addType } from "pmcf";
13
+
14
+ export class Core {
15
+ static name = "core";
16
+ static priority = 1;
17
+
18
+ static {
19
+ addType(this);
20
+ }
21
+
22
+ extends = new Set();
23
+
24
+ constructor(owner, data) {
25
+ if (owner) {
26
+ this.owner = owner;
27
+ }
28
+ }
29
+
30
+ set owner(value) {
31
+ if (this === value || this === value?.owner) {
32
+ this.error("Unable to own myself", value.fullName);
33
+ } else {
34
+ this._owner = value;
35
+ }
36
+ }
37
+
38
+ get owner() {
39
+ return this._owner;
40
+ }
41
+
42
+ forOwner(owner) {
43
+ if (this.owner !== owner) {
44
+ const newObject = Object.create(this);
45
+ newObject.owner = owner;
46
+ return newObject;
47
+ }
48
+
49
+ return this;
50
+ }
51
+
52
+ materializeExtends() {
53
+ for (const [path, attribute] of extendingAttributeIterator(
54
+ this.constructor,
55
+ attribute => attribute.collection && !attribute.type.primitive
56
+ )) {
57
+ if (attribute.deferredExpression) {
58
+ const name = attribute.name;
59
+ if (!this.hasOwnProperty(name)) {
60
+ for (const e of this.walkDirections(["extends"])) {
61
+ if (e.hasOwnProperty(name)) {
62
+ Object.defineProperty(this, name, {
63
+ get: () => e[name]
64
+ });
65
+ break;
66
+ }
67
+ }
68
+ }
69
+
70
+ continue;
71
+ }
72
+
73
+ const collection = this[attribute.name];
74
+
75
+ if (typeof collection?.get === "function") {
76
+ for (const [name, extending] of this.mapFromDirections(
77
+ ["extends"],
78
+ attribute.name
79
+ )) {
80
+ const present = collection.get(extending.name);
81
+
82
+ if (present) {
83
+ present.extends.add(extending);
84
+ present.materializeExtends();
85
+ } else {
86
+ collection.set(extending.name, extending.forOwner(this));
87
+ }
88
+ }
89
+ } /*else {
90
+ if (Array.isArray(collection)) {
91
+ // TODO
92
+ } else {
93
+ //console.log("EXTENDS", this.fullName, attribute.name);
94
+
95
+ for (const extending of this.unionFromDirections(
96
+ ["extends"],
97
+ attribute.name
98
+ )) {
99
+ if (!collection.has(extending)) {
100
+ //console.log("ADD", this.fullName, extending.fullName);
101
+ collection.add(extending);
102
+ }
103
+ }
104
+ }
105
+ }*/
106
+ }
107
+ }
108
+
109
+ get typeName() {
110
+ return this.constructor.name;
111
+ }
112
+
113
+ /**
114
+ * Retrive attribute values from an object.
115
+ * @param {Function} [filter]
116
+ * @return {Iterable<[string,any]>} values
117
+ */
118
+ *attributeIterator(filter) {
119
+ for (const [path, attribute] of extendingAttributeIterator(
120
+ this.constructor,
121
+ filter
122
+ )) {
123
+ const name = path.join(".");
124
+ const value = this.attribute(name);
125
+
126
+ if (value !== undefined) {
127
+ yield [
128
+ attribute.externalName ?? name,
129
+ toExternal(value, attribute),
130
+ path,
131
+ attribute
132
+ ];
133
+ }
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Retrive attribute values from an object.
139
+ * @param {Function} [filter]
140
+ * @return {Object} values
141
+ */
142
+ getAttributes(filter = filterPublic) {
143
+ return Object.fromEntries(this.attributeIterator(filter));
144
+ }
145
+
146
+ value(name) {
147
+ return this.attribute(name);
148
+ }
149
+
150
+ /**
151
+ *
152
+ * @param {string} name
153
+ * @returns {any}
154
+ */
155
+ property(name) {
156
+ for (const node of this.walkDirections()) {
157
+ const value = node.properties[name];
158
+
159
+ if (value !== undefined) {
160
+ return this.expand(value);
161
+ }
162
+ }
163
+ }
164
+
165
+ /**
166
+ *
167
+ * @param {string} name
168
+ * @returns {any}
169
+ */
170
+ attribute(name) {
171
+ for (const node of this.walkDirections(["this", "extends"])) {
172
+ const value = getAttribute(node, name);
173
+ if (value !== undefined) {
174
+ return this.expand(value);
175
+ }
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Walk the object graph in some directions and deliver seen nodes.
181
+ * @param {string[]} directions
182
+ * @return {Iterable<Core>}
183
+ */
184
+ *walkDirections(directions = ["this", "extends", "owner"]) {
185
+ if (directions.indexOf("this") >= 0) {
186
+ yield this;
187
+ directions = directions.filter(d => d !== "this");
188
+ }
189
+
190
+ yield* this._walkDirections(directions, new Set());
191
+ }
192
+
193
+ *_walkDirections(directions, seen) {
194
+ if (!seen.has(this)) {
195
+ seen.add(this);
196
+
197
+ for (const direction of directions) {
198
+ const value = this[direction];
199
+
200
+ if (value) {
201
+ if (value[Symbol.iterator]) {
202
+ for (const node of value) {
203
+ yield node;
204
+ yield* node._walkDirections(directions, seen);
205
+ }
206
+ } else {
207
+ yield value;
208
+ yield* value._walkDirections(directions, seen);
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Deliver AggregatedMap of all property Maps.
217
+ * @param {string[]} directions
218
+ * @param {string} property
219
+ * @returns {Map<any,any>}
220
+ */
221
+ mapFromDirections(directions, property) {
222
+ return new AggregatedMap(
223
+ [...this.walkDirections(directions)]
224
+ .map(node => node[property])
225
+ .filter(node => node !== undefined)
226
+ );
227
+ }
228
+
229
+ /**
230
+ * Deliver union set of all property values.
231
+ * @param {string[]} directions
232
+ * @param {string} property
233
+ * @returns {Set<any>}
234
+ */
235
+ unionFromDirections(directions, property) {
236
+ let collected = new Set();
237
+ for (const node of this.walkDirections(directions)) {
238
+ const value = node[property];
239
+ if (value !== undefined) {
240
+ if (!(value instanceof Set)) {
241
+ console.log("NO SET", value, node.fullName, property);
242
+ }
243
+ collected = collected.union(value);
244
+ }
245
+ }
246
+
247
+ return collected;
248
+ }
249
+
250
+ get children() {
251
+ const all = [];
252
+
253
+ for (const [path, attribute] of extendingAttributeIterator(
254
+ this.constructor,
255
+ attribute => attribute.backpointer?.name === "owner"
256
+ )) {
257
+ const value = this[path];
258
+
259
+ if (value !== undefined) {
260
+ if (attribute.collection) {
261
+ if (typeof value.values === "function") {
262
+ all.push(...value.values());
263
+ } else {
264
+ if (value instanceof Iterator) {
265
+ all.push(...value);
266
+ } else {
267
+ if (value instanceof Core) {
268
+ this.error(
269
+ `Unexpected scalar value for "${attribute.name}"`,
270
+ value.fullName
271
+ );
272
+ all.push(value); // TODO should not happen
273
+ } else if (typeof value === "object") {
274
+ all.push(...Object.values(value));
275
+ }
276
+ }
277
+ }
278
+ } else {
279
+ all.push(value);
280
+ }
281
+ }
282
+ }
283
+
284
+ return all;
285
+ }
286
+
287
+ /**
288
+ *
289
+ * @param {any} object
290
+ * @returns {any}
291
+ */
292
+ expand(object) {
293
+ if (this.isTemplate || object instanceof Core) {
294
+ return object;
295
+ }
296
+
297
+ return expand(object, {
298
+ stopClass: Core,
299
+ root: this.root,
300
+ current: this,
301
+ valueFor: (name, at) =>
302
+ typeof at?.value === "function" ? at.value(name) : globals[name]
303
+ });
304
+ }
305
+
306
+ /**
307
+ *
308
+ * @param {string} expression
309
+ * @param {object} options
310
+ * @returns {any}
311
+ */
312
+ expression(expression, options) {
313
+ return parse(expression, {
314
+ root: this.root,
315
+ current: this,
316
+ valueFor: (name, at) =>
317
+ typeof at?.value === "function" ? at.value(name) : globals[name],
318
+ ...options
319
+ });
320
+ }
321
+
322
+ get isTemplate() {
323
+ return false;
324
+ }
325
+ }
package/src/host.mjs CHANGED
@@ -5,7 +5,6 @@ import { AggregatedMap } from "aggregated-map";
5
5
  import {
6
6
  string_attribute,
7
7
  string_attribute_writable,
8
- string_set_attribute_writable,
9
8
  number_attribute_writable,
10
9
  priority_attribute,
11
10
  asArray
@@ -19,12 +18,7 @@ import {
19
18
  } from "./common-attributes.mjs";
20
19
  import { ServiceOwner } from "./service-owner.mjs";
21
20
  import { addHook } from "./hooks.mjs";
22
- import {
23
- domainFromDominName,
24
- domainName,
25
- writeLines,
26
- union
27
- } from "./utils.mjs";
21
+ import { domainFromDominName, domainName, writeLines } from "./utils.mjs";
28
22
  import { loadHooks } from "./hooks.mjs";
29
23
  import { generateKnownHosts } from "./host-utils.mjs";
30
24
 
@@ -75,10 +69,6 @@ export class Host extends ServiceOwner {
75
69
  name: "architecture",
76
70
  values: new Set(["x86", "x86_64", "aarch64", "armv7", "riscv"])
77
71
  },
78
- replaces: { ...string_set_attribute_writable, name: "replaces" },
79
- depends: { ...string_set_attribute_writable, name: "depends" },
80
- provides: { ...string_set_attribute_writable, name: "provides" },
81
- optional: { ...string_set_attribute_writable, name: "optional" },
82
72
  extends: {
83
73
  ...extends_attribute,
84
74
  type: Host
@@ -91,10 +81,6 @@ export class Host extends ServiceOwner {
91
81
  }
92
82
 
93
83
  _networkInterfaces = new Map();
94
- _provides = new Set();
95
- _replaces = new Set();
96
- _depends = new Set();
97
- _optional = new Set();
98
84
  _os;
99
85
  _distribution;
100
86
  _deployment;
@@ -152,12 +138,6 @@ export class Host extends ServiceOwner {
152
138
  return this.attribute("_architecture");
153
139
  }
154
140
 
155
- get derivedPackaging() {
156
- return this.expand(
157
- this.unionFromDirections(["this", "extends"], "_packaging")
158
- );
159
- }
160
-
161
141
  get isTemplate() {
162
142
  return this.isModel || super.isTemplate;
163
143
  }
@@ -174,46 +154,6 @@ export class Host extends ServiceOwner {
174
154
  }
175
155
  }
176
156
 
177
- set provides(value) {
178
- this._provides = union(value, this._provides);
179
- }
180
-
181
- get provides() {
182
- return this.expand(
183
- this.unionFromDirections(["this", "extends"], "_provides")
184
- );
185
- }
186
-
187
- set replaces(value) {
188
- this._replaces = union(value, this._replaces);
189
- }
190
-
191
- get replaces() {
192
- return this.expand(
193
- this.unionFromDirections(["this", "extends"], "_replaces")
194
- );
195
- }
196
-
197
- set depends(value) {
198
- this._depends = union(value, this._depends);
199
- }
200
-
201
- get depends() {
202
- return this.expand(
203
- this.unionFromDirections(["this", "extends"], "_depends")
204
- );
205
- }
206
-
207
- set optional(value) {
208
- this._optional = union(value, this._optional);
209
- }
210
-
211
- get optional() {
212
- return this.expand(
213
- this.unionFromDirections(["this", "extends"], "_optional")
214
- );
215
- }
216
-
217
157
  set os(value) {
218
158
  this._os = value;
219
159
  }
@@ -365,34 +305,20 @@ export class Host extends ServiceOwner {
365
305
  }
366
306
 
367
307
  async publicKey(type = "ed25519") {
368
- return readFile(join(this.directory, `ssh_host_${type}_key.pub`), "utf8");
308
+ return readFile(
309
+ join(this.directory, "content", "etc", "ssh", `ssh_host_${type}_key.pub`),
310
+ "utf8"
311
+ );
369
312
  }
370
313
 
371
314
  async *preparePackages(dir) {
372
315
  const packageData = this.packageData;
316
+
373
317
  packageData.sources.push(
374
318
  await Array.fromAsync(this.templateContent()),
375
- new FileContentProvider(
376
- { dir: this.directory, pattern: "*.pub" },
377
- { destination: "/etc/ssh/", mode: 0o644 }
378
- ),
379
- new FileContentProvider(
380
- { dir: this.directory, pattern: "*_key" },
381
- { destination: "/etc/ssh/", mode: 0o600 }
382
- ),
383
319
  new FileContentProvider({ dir, pattern: ["**/*", "**/.ssh/*"] })
384
320
  );
385
321
 
386
- Object.assign(packageData.properties, {
387
- description: `${this.typeName} definitions for ${this.fullName}`,
388
- dependencies: [...this.depends],
389
- provides: [...this.provides],
390
- replaces: [...this.replaces],
391
- depends: [...this.depends],
392
- optional: [...this.optional],
393
- backup: "root/.ssh/known_hosts"
394
- });
395
-
396
322
  await loadHooks(
397
323
  packageData,
398
324
  new URL("host.install", import.meta.url).pathname
@@ -412,8 +338,6 @@ export class Host extends ServiceOwner {
412
338
  for (const { serviceName, configFileName, content } of asArray(
413
339
  service.expand(service.systemdConfigs(this.name))
414
340
  )) {
415
- //console.log("SERVICE", service.fullName, configFileName);
416
-
417
341
  await writeLines(dir, configFileName, content);
418
342
 
419
343
  addHook(
package/src/module.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./type.mjs";
2
+ export * from "./core.mjs";
2
3
  export * from "./base.mjs";
3
4
  export * from "./cluster.mjs";
4
5
  export * from "./owner.mjs";
@@ -8,6 +9,7 @@ export * from "./service-owner.mjs";
8
9
  export * from "./network.mjs";
9
10
  export * from "./network-address.mjs";
10
11
  export * from "./common-attributes.mjs";
12
+ export * from "./content.mjs";
11
13
  export * from "./host.mjs";
12
14
  export * from "./network-interfaces/network-interface.mjs";
13
15
  export * from "./network-interfaces/loopback.mjs";
@@ -825,17 +825,17 @@ export class bind extends CoreService {
825
825
  }
826
826
 
827
827
  async *preparePackages(dir) {
828
- const permissions = this.packageContentPermissions;
828
+ const permissions = this.content.permissions;
829
829
  const packageData = this.packageData;
830
830
 
831
831
  packageData.sources = await Array.fromAsync(
832
- this.templateContent(...permissions)
832
+ this.templateContent(permissions)
833
833
  );
834
834
 
835
835
  let hasContent = packageData.sources.length > 0;
836
836
 
837
837
  packageData.sources.push(
838
- new FileContentProvider(dir + "/", ...permissions)
838
+ new FileContentProvider(dir + "/", permissions)
839
839
  );
840
840
 
841
841
  const outputControl = { packageData, dir, permissions };
@@ -58,7 +58,7 @@ export class mosquitto extends CoreService {
58
58
  wd.map(n => [n.fullName, n.directory])
59
59
  );*/
60
60
 
61
- const permissions = this.packageContentPermissions;
61
+ const permissions = this.content.permissions;
62
62
  const packageData = this.packageData;
63
63
 
64
64
  packageData.sources = await Array.fromAsync(
@@ -66,7 +66,7 @@ export class mosquitto extends CoreService {
66
66
  );
67
67
 
68
68
  packageData.sources.push(
69
- new FileContentProvider(dir + "/", ...permissions)
69
+ new FileContentProvider(dir + "/", permissions)
70
70
  );
71
71
 
72
72
  await writeLines(
package/src/subnet.mjs CHANGED
@@ -5,16 +5,11 @@ import {
5
5
  matchPrefixIP,
6
6
  FAMILY_IPV6
7
7
  } from "ip-utilties";
8
- import {
9
- string_attribute,
10
- name_attribute,
11
- integer_attribute,
12
- getAttribute
13
- } from "pacc";
8
+ import { string_attribute, name_attribute, integer_attribute } from "pacc";
14
9
  import { networks_attribute } from "./common-attributes.mjs";
15
- import { addType, Network } from "pmcf";
10
+ import { addType, Network, Core } from "pmcf";
16
11
 
17
- export class Subnet {
12
+ export class Subnet extends Core {
18
13
  static name = "subnet";
19
14
  static priority = 1;
20
15
  static owners = ["owner", "network", "network_interface", "root"];
@@ -34,6 +29,7 @@ export class Subnet {
34
29
  networks = new Set();
35
30
 
36
31
  constructor(owner, address) {
32
+ super();
37
33
  const { longPrefix, prefix, prefixLength, cidr, family } =
38
34
  normalizeCIDR(address);
39
35
 
@@ -44,27 +40,13 @@ export class Subnet {
44
40
  this.family = family;
45
41
  }
46
42
 
47
- get owner() {
48
- return this._owner;
49
- }
50
-
51
43
  set owner(value) {
52
- this._owner = value;
44
+ super.owner = value;
53
45
  if (value instanceof Network) {
54
46
  this.networks.add(value);
55
47
  }
56
48
  }
57
49
 
58
- attribute(name) {
59
- return getAttribute(this, name);
60
- }
61
-
62
- value(name) {
63
- return this.attribute(name);
64
- }
65
-
66
- *_walkDirections(directions, seen) {}
67
-
68
50
  get cidr() {
69
51
  return this.address;
70
52
  }