dal-engine-core-js-lib-dev 0.0.0 → 0.0.2

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/dist/index.esm.js CHANGED
@@ -52,6 +52,18 @@ ENGINE_TYPES$1 = Object.freeze(ENGINE_TYPES$1);
52
52
 
53
53
  var ENGINE_TYPES = ENGINE_TYPES$1;
54
54
 
55
+ class MissingAttributes extends DALEngineError {
56
+ constructor (type, attribute) {
57
+ let msg;
58
+ if (Array.isArray(attribute) && attribute.length > 1) {
59
+ msg = `"${type}" must be initialized with the attributes "${attribute}".`;
60
+ } else {
61
+ msg = `"${type}" must be initialized with the attribute "${attribute}".`;
62
+ }
63
+ super(msg);
64
+ }
65
+ }
66
+
55
67
  /**
56
68
  * Class representing a Invariant in the design.
57
69
  */
@@ -65,16 +77,34 @@ class Invariant extends Base {
65
77
  super();
66
78
  this.type = ENGINE_TYPES.INVARIANT;
67
79
  this.invariantViolated = false;
68
- if (typeof args === "object" && args !== null) {
69
- if (Object.hasOwn(args, "uid")) {
70
- this.loadInvariantFromJSON(args);
71
- } else {
72
- this.name = args.name;
73
- this.rule = args.rule;
74
- }
80
+ this.invariantType = null;
81
+ this.traceId = null;
82
+ if (typeof args === "object" && Object.hasOwn(args, "uid")) {
83
+ this.loadInvariantFromJSON(args);
84
+ } else {
85
+ this.loadArgs(args);
75
86
  }
76
87
  }
77
88
 
89
+ /**
90
+ * Loads the provided arguments.
91
+ * @throws {MissingAttributes} Thrown when required attr is not present.
92
+ * @param {Object} args
93
+ */
94
+ loadArgs (args) {
95
+ const expectedAttributes = ["name", "rule"];
96
+ if (typeof args !== "object" || args === null || Array.isArray(args)) {
97
+ // Not an object, so all attributes are missing.
98
+ throw new MissingAttributes("Invariant", expectedAttributes);
99
+ }
100
+ expectedAttributes.forEach((attr) => {
101
+ if (!(attr in args)) {
102
+ throw new MissingAttributes("Invariant", attr);
103
+ }
104
+ this[attr] = args[attr];
105
+ });
106
+ }
107
+
78
108
  /**
79
109
  * Loads the participant from a JSON object.
80
110
  * @param {Object} invariantJSON
@@ -107,13 +137,52 @@ class Invariant extends Base {
107
137
  enforceMinLength (value) {
108
138
  if ("keys" in this.rule) {
109
139
  for (let i = 0; i < this.rule["keys"].length; i++) {
110
- console.log(this.rule["keys"][i], value);
111
140
  value = value[this.rule["keys"][i]];
112
141
  }
113
142
  } if (value === null || typeof value !== "string" || value.length < this.rule.value) {
114
143
  this.invariantViolated = true;
115
144
  }
116
145
  }
146
+
147
+
148
+ /**
149
+ * Sets the invariant type.
150
+ *
151
+ * The two types of invariants are: Intrinsic and Substrate
152
+ *
153
+ * Substrate invariants are learnt by the design from the
154
+ * environment.
155
+ *
156
+ * Intrinsic invariants are arrived at naturally from the
157
+ * designs control flow, data dependencies and semantic assumptions.
158
+ *
159
+ * @param {String} invariantType
160
+ */
161
+ setInvariantType (invariantType) {
162
+ // TODO: Add validation for invariantType.
163
+ this.invariantType = invariantType;
164
+ }
165
+
166
+ /**
167
+ * This function adds the trace id which can be used for
168
+ * automated testing.
169
+ *
170
+ * Substrate invariants correspond to a trace that represents
171
+ * an environment that reveals a limitation of the substrate,
172
+ * thus motivating the invariant. It is also the environment
173
+ * in which an implementation can prove that it respects this
174
+ * invariant.
175
+ *
176
+ * Intrisinc invariants correspond to a trace that represents
177
+ * a factory default environment that enables the implementation
178
+ * to prove that it respects the invariant.
179
+ *
180
+ * @param {String} traceId ID of trace used for automated testing.
181
+ */
182
+ setTraceId (traceId) {
183
+ // TODO: Add validation for traceId.
184
+ this.traceId = traceId;
185
+ }
117
186
  }
118
187
 
119
188
  /**
@@ -129,16 +198,34 @@ class Participant extends Base {
129
198
  super();
130
199
  this.type = ENGINE_TYPES.INVARIANT;
131
200
  this.invariants = [];
201
+ this.abstractionId = null;
132
202
  this.invariantViolated = false;
133
- if (typeof args === "object" && args !== null) {
134
- if (Object.hasOwn(args, "uid")) {
135
- this.loadParticipantFromJSON(args);
136
- } else {
137
- this.name = args.name;
138
- }
203
+ if (typeof args === "object" && Object.hasOwn(args, "uid")) {
204
+ this.loadParticipantFromJSON(args);
205
+ } else {
206
+ this.loadArgs(args);
139
207
  }
140
208
  }
141
209
 
210
+ /**
211
+ * Loads the provided arguments.
212
+ * @throws {MissingAttributes} Thrown when required attr is not present.
213
+ * @param {Object} args
214
+ */
215
+ loadArgs (args) {
216
+ const expectedAttributes = ["name"];
217
+ if (typeof args !== "object" || args === null || Array.isArray(args)) {
218
+ // Not an object, so all attributes are missing.
219
+ throw new MissingAttributes("Participant", expectedAttributes);
220
+ }
221
+ expectedAttributes.forEach((attr) => {
222
+ if (!(attr in args)) {
223
+ throw new MissingAttributes("Participant", attr);
224
+ }
225
+ this[attr] = args[attr];
226
+ });
227
+ }
228
+
142
229
  /**
143
230
  * Loads the participant from a JSON object.
144
231
  * @param {Object} participantJSON
@@ -185,6 +272,18 @@ class Participant extends Base {
185
272
  }
186
273
  return this.invariantViolated;
187
274
  }
275
+
276
+ /**
277
+ * Map the abstraction ID from the execution to the participant.
278
+ *
279
+ * This abstraction id will be used to assign a value to the
280
+ * participant from the execution using the logged abstraction id.
281
+ *
282
+ * @param {String} abstractionId
283
+ */
284
+ mapAbstraction (abstractionId) {
285
+ this.abstractionId = abstractionId;
286
+ }
188
287
  }
189
288
 
190
289
  /**
@@ -200,16 +299,34 @@ class Behavior extends Base {
200
299
  super();
201
300
  this.type = ENGINE_TYPES.BEHAVIOR;
202
301
  this.participants = [];
302
+ this.abstractionIds = [];
203
303
  this.invalidWorldState = false;
204
- if (typeof args === "object" && args !== null) {
205
- if (Object.hasOwn(args, "uid")) {
206
- this.loadBehaviorFromJSON(args);
207
- } else {
208
- this.name = args.name;
209
- }
304
+ if (typeof args === "object" && Object.hasOwn(args, "uid")) {
305
+ this.loadBehaviorFromJSON(args);
306
+ } else {
307
+ this.loadArgs(args);
210
308
  }
211
309
  }
212
310
 
311
+ /**
312
+ * Loads the provided arguments.
313
+ * @throws {MissingAttributes} Thrown when required attr is not present.
314
+ * @param {Object} args
315
+ */
316
+ loadArgs (args) {
317
+ const expectedAttributes = ["name"];
318
+ if (typeof args !== "object" || args === null || Array.isArray(args)) {
319
+ // Not an object, so all attributes are missing.
320
+ throw new MissingAttributes("Behavior", expectedAttributes);
321
+ }
322
+ expectedAttributes.forEach((attr) => {
323
+ if (!(attr in args)) {
324
+ throw new MissingAttributes("Behavior", attr);
325
+ }
326
+ this[attr] = args[attr];
327
+ });
328
+ }
329
+
213
330
  /**
214
331
  * Loads the behavior from a JSON object.
215
332
  * @param {Object} behaviorJSON
@@ -239,17 +356,21 @@ class Behavior extends Base {
239
356
  * @param {*} value
240
357
  */
241
358
  setParticipantValue (participantName, value) {
242
- for (let i = 0; i < this.participants.length; i++) {
243
- const participant = this.participants[i];
244
- if (participant.name === participantName) {
245
- participant.value = value;
246
- const violation = participant.enforceInvariants();
247
- if (violation) {
248
- this.invalidWorldState = true;
249
- }
250
- }
359
+ const participant = this.participants.find(obj => obj.name === participantName);
360
+ participant.value = value;
361
+ const violation = participant.enforceInvariants();
362
+ if (violation) {
363
+ this.invalidWorldState = true;
251
364
  }
252
365
  }
366
+
367
+ /**
368
+ * Maps the abstraction id from execution to the behavior.
369
+ * @param {String} abstractionId
370
+ */
371
+ addMapping (abstractionId) {
372
+ this.abstractionIds.push(abstractionId);
373
+ }
253
374
  }
254
375
 
255
376
  /**
@@ -264,13 +385,13 @@ class GraphNode extends Base {
264
385
  constructor (args) {
265
386
  super();
266
387
  this.type = ENGINE_TYPES.GRAPH_NODE;
267
- this.goToBehaviors = [];
388
+ this.goToBehaviorsIds = [];
268
389
  if (typeof args === "object" && args !== null) {
269
390
  if (Object.hasOwn(args, "uid")) {
270
391
  this.loadNodeFromJSON(args);
271
392
  } else {
272
393
  this.behavior = args.behavior;
273
- this.goToBehaviors = args.goToBehaviors;
394
+ this.goToBehaviorsIds = args.goToBehaviorsIds;
274
395
  }
275
396
  }
276
397
  }
@@ -283,13 +404,22 @@ class GraphNode extends Base {
283
404
  for (const [key, value] of Object.entries(nodesJSON)) {
284
405
  if (key === "behavior") {
285
406
  this.behavior = new Behavior(value);
286
- } else if (key === "goToBehaviors") {
287
- value.forEach(node => this.goToBehaviors.push(new Behavior(node)));
407
+ } else if (key === "goToBehaviorsIds") {
408
+ value.forEach(behaviorId => this.goToBehaviorsIds.push(behaviorId));
288
409
  } else {
289
410
  this[key] = nodesJSON[key];
290
411
  }
291
412
  } }
292
413
 
414
+ /**
415
+ * Adds a behavior name to the list of behaviors that this
416
+ * node transitions to.
417
+ * @param {String} behaviorId ID of behavior.
418
+ */
419
+ addGoToBehavior (behaviorId) {
420
+ this.goToBehaviorsIds.push(behaviorId);
421
+ }
422
+
293
423
  /**
294
424
  * Checks if the provided behavior name is a valid
295
425
  * behavior that the control flow selects as a
@@ -299,9 +429,9 @@ class GraphNode extends Base {
299
429
  * @returns {Boolean}
300
430
  */
301
431
  isValidGoToBehavior (behaviorName) {
302
- for (let i = 0; i < this.goToBehaviors.length; i++) {
303
- const behavior = this.goToBehaviors[i];
304
- if (behavior.name === behaviorName) {
432
+ for (let i = 0; i < this.goToBehaviorsIds.length; i++) {
433
+ const behaviorId = this.goToBehaviorsIds[i];
434
+ if (behaviorId === behaviorName) {
305
435
  return true;
306
436
  }
307
437
  }
@@ -347,13 +477,13 @@ class BehavioralControlGraph extends Base {
347
477
  /**
348
478
  * Adds a node to the graph.
349
479
  * @param {Behavior} behavior
350
- * @param {Array} goToBehaviors
480
+ * @param {Array} goToBehaviorsIds
351
481
  * @returns
352
482
  */
353
- addNode (behavior, goToBehaviors) {
483
+ addNode (behavior, goToBehaviorsIds) {
354
484
  const node = new GraphNode({
355
485
  behavior: behavior,
356
- goToBehaviors: goToBehaviors,
486
+ goToBehaviorsIds: goToBehaviorsIds,
357
487
  });
358
488
  this.nodes.push(node);
359
489
  return node;
@@ -410,6 +540,20 @@ class BehavioralControlGraph extends Base {
410
540
  throw new InvalidTransitionError(this.currentNode.behavior.name, nextBehaviorName);
411
541
  }
412
542
  }
543
+
544
+ /**
545
+ * Exports the graph represented using mermaid syntax for visualization.
546
+ * @returns {String} Graph as mermaid diagram.
547
+ */
548
+ exportAsMermaid () {
549
+ let mermaid = "flowchart TD\n";
550
+ this.nodes.forEach((node) => {
551
+ node.goToBehaviorsIds.forEach((behaviorId) => {
552
+ mermaid += ` ${node.behavior.name} --> ${behaviorId}\n`;
553
+ });
554
+ });
555
+ return mermaid;
556
+ }
413
557
  }
414
558
 
415
559
  /**
@@ -417,16 +561,37 @@ class BehavioralControlGraph extends Base {
417
561
  * abstraction language. It exposes functions
418
562
  * configure the engine through the DAL specification.
419
563
  *
420
- * The execution of an program instrumented with the
421
- * same design be used to step through the design
422
- * while the engine automatically debugs the execution.
564
+ * The design specified in this engine is mapped onto
565
+ * the implementation using abstraction ids. The
566
+ * implementation is then instrumented and the resulting
567
+ * execution trace is fed back into the engine and is
568
+ * automatically debugged by transforming the execution
569
+ * into the behavior of the design and enforcing the
570
+ * invariants.
423
571
  */
424
572
  class DALEngine {
425
573
  constructor (args) {
426
574
  this.graph = new BehavioralControlGraph();
427
- for (const [key, value] of Object.entries(args)) {
428
- this[key] = value;
575
+ this.loadArgs(args);
576
+ }
577
+
578
+ /**
579
+ * Loads the provided arguments.
580
+ * @throws {MissingAttributes} Thrown when required attr is not present.
581
+ * @param {Object} args
582
+ */
583
+ loadArgs (args) {
584
+ const expectedAttributes = ["name"];
585
+ if (typeof args !== "object" || args === null || Array.isArray(args)) {
586
+ // Not an object, so all attributes are missing.
587
+ throw new MissingAttributes("Engine", expectedAttributes);
429
588
  }
589
+ expectedAttributes.forEach((attr) => {
590
+ if (!(attr in args)) {
591
+ throw new MissingAttributes("Engine", attr);
592
+ }
593
+ this[attr] = args[attr];
594
+ });
430
595
  }
431
596
 
432
597
  /**
@@ -452,9 +617,6 @@ class DALEngine {
452
617
  * @returns {Participant}
453
618
  */
454
619
  createParticipant (args) {
455
- // TODO: Validate that the args have the necessary keys
456
- // and raise custom error if they are missing.
457
- // Perhaps it is better to do that in the class itself.
458
620
  return new Participant(args);
459
621
  }
460
622
 
@@ -464,8 +626,6 @@ class DALEngine {
464
626
  * @returns {Behavior}
465
627
  */
466
628
  createBehavior (args) {
467
- // TODO: Validate that the args have the necessary keys
468
- // and raise custom error if they are missing.
469
629
  return new Behavior(args);
470
630
  }
471
631
 
@@ -475,10 +635,45 @@ class DALEngine {
475
635
  * @returns {Invariant}
476
636
  */
477
637
  createInvariant (args) {
478
- // TODO: Validate that the args have the necessary keys
479
- // and raise custom error if they are missing.
480
638
  return new Invariant(args);
481
639
  }
640
+
641
+
642
+ /**
643
+ * Returns the node in the graph with the given behavior name.
644
+ * @param {String} behaviorId
645
+ * @returns {GraphNode}
646
+ */
647
+ getNode (behaviorId) {
648
+ return this.graph.findNode(behaviorId);
649
+ }
650
+
651
+ /**
652
+ * Adds a node to the graph with the given behaviorId and goToBehaviors.
653
+ * @param {String} behaviorId
654
+ * @param {Array} goToBehaviorsIds
655
+ * @returns {GraphNode}
656
+ */
657
+ addNode (behaviorId, goToBehaviorsIds) {
658
+ const behavior = this.createBehavior({name: behaviorId});
659
+ return this.graph.addNode(behavior, goToBehaviorsIds);
660
+ }
661
+
662
+ /**
663
+ * Adds a goToBehavior to the node with the given behaviorId.
664
+ * @param {String} behaviorId
665
+ * @param {String|Array} goToBehaviorIds
666
+ * @returns {GraphNode}
667
+ */
668
+ addGoToBehavior (behaviorId, goToBehaviorIds) {
669
+ const node = this.graph.findNode(behaviorId);
670
+ if (Array.isArray(goToBehaviorIds)) {
671
+ node.goToBehaviorsIds.push(...goToBehaviorIds);
672
+ } else {
673
+ node.goToBehaviorsIds.push(goToBehaviorIds);
674
+ }
675
+ return node;
676
+ }
482
677
  }
483
678
 
484
679
  export { DALEngine };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dal-engine-core-js-lib-dev",
3
- "version": "0.0.0",
3
+ "version": "0.0.2",
4
4
  "main": "dist/index.cjs",
5
5
  "module": "dist/index.esm.js",
6
6
  "type": "module",
@@ -43,13 +43,13 @@ class BehavioralControlGraph extends Base {
43
43
  /**
44
44
  * Adds a node to the graph.
45
45
  * @param {Behavior} behavior
46
- * @param {Array} goToBehaviors
46
+ * @param {Array} goToBehaviorsIds
47
47
  * @returns
48
48
  */
49
- addNode (behavior, goToBehaviors) {
49
+ addNode (behavior, goToBehaviorsIds) {
50
50
  const node = new GraphNode({
51
51
  behavior: behavior,
52
- goToBehaviors: goToBehaviors,
52
+ goToBehaviorsIds: goToBehaviorsIds,
53
53
  });
54
54
  this.nodes.push(node);
55
55
  return node;
@@ -106,6 +106,20 @@ class BehavioralControlGraph extends Base {
106
106
  throw new InvalidTransitionError(this.currentNode.behavior.name, nextBehaviorName);
107
107
  }
108
108
  }
109
- }
109
+
110
+ /**
111
+ * Exports the graph represented using mermaid syntax for visualization.
112
+ * @returns {String} Graph as mermaid diagram.
113
+ */
114
+ exportAsMermaid () {
115
+ let mermaid = "flowchart TD\n";
116
+ this.nodes.forEach((node) => {
117
+ node.goToBehaviorsIds.forEach((behaviorId) => {
118
+ mermaid += ` ${node.behavior.name} --> ${behaviorId}\n`;
119
+ });
120
+ });
121
+ return mermaid;
122
+ }
123
+ };
110
124
 
111
125
  export default BehavioralControlGraph;
@@ -13,13 +13,13 @@ class GraphNode extends Base {
13
13
  constructor (args) {
14
14
  super();
15
15
  this.type = ENGINE_TYPES.GRAPH_NODE;
16
- this.goToBehaviors = [];
16
+ this.goToBehaviorsIds = [];
17
17
  if (typeof args === "object" && args !== null) {
18
18
  if (Object.hasOwn(args, "uid")) {
19
19
  this.loadNodeFromJSON(args);
20
20
  } else {
21
21
  this.behavior = args.behavior;
22
- this.goToBehaviors = args.goToBehaviors;
22
+ this.goToBehaviorsIds = args.goToBehaviorsIds;
23
23
  }
24
24
  }
25
25
  }
@@ -32,14 +32,23 @@ class GraphNode extends Base {
32
32
  for (const [key, value] of Object.entries(nodesJSON)) {
33
33
  if (key === "behavior") {
34
34
  this.behavior = new Behavior(value);
35
- } else if (key === "goToBehaviors") {
36
- value.forEach(node => this.goToBehaviors.push(new Behavior(node)));
35
+ } else if (key === "goToBehaviorsIds") {
36
+ value.forEach(behaviorId => this.goToBehaviorsIds.push(behaviorId));
37
37
  } else {
38
38
  this[key] = nodesJSON[key];
39
39
  }
40
40
  };
41
41
  }
42
42
 
43
+ /**
44
+ * Adds a behavior name to the list of behaviors that this
45
+ * node transitions to.
46
+ * @param {String} behaviorId ID of behavior.
47
+ */
48
+ addGoToBehavior (behaviorId) {
49
+ this.goToBehaviorsIds.push(behaviorId);
50
+ }
51
+
43
52
  /**
44
53
  * Checks if the provided behavior name is a valid
45
54
  * behavior that the control flow selects as a
@@ -49,9 +58,9 @@ class GraphNode extends Base {
49
58
  * @returns {Boolean}
50
59
  */
51
60
  isValidGoToBehavior (behaviorName) {
52
- for (let i = 0; i < this.goToBehaviors.length; i++) {
53
- const behavior = this.goToBehaviors[i];
54
- if (behavior.name === behaviorName) {
61
+ for (let i = 0; i < this.goToBehaviorsIds.length; i++) {
62
+ const behaviorId = this.goToBehaviorsIds[i];
63
+ if (behaviorId === behaviorName) {
55
64
  return true;
56
65
  }
57
66
  }
package/src/DALEngine.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import BehavioralControlGraph from "./BehavioralControlGraph/BehavioralControlGraph";
2
+ import MissingAttributes from "./Errors/MissingAttributes";
2
3
  import Behavior from "./Members/Behavior";
3
4
  import Invariant from "./Members/Invariant";
4
5
  import Participant from "./Members/Participant";
@@ -8,16 +9,37 @@ import Participant from "./Members/Participant";
8
9
  * abstraction language. It exposes functions
9
10
  * configure the engine through the DAL specification.
10
11
  *
11
- * The execution of an program instrumented with the
12
- * same design be used to step through the design
13
- * while the engine automatically debugs the execution.
12
+ * The design specified in this engine is mapped onto
13
+ * the implementation using abstraction ids. The
14
+ * implementation is then instrumented and the resulting
15
+ * execution trace is fed back into the engine and is
16
+ * automatically debugged by transforming the execution
17
+ * into the behavior of the design and enforcing the
18
+ * invariants.
14
19
  */
15
20
  export class DALEngine {
16
21
  constructor (args) {
17
22
  this.graph = new BehavioralControlGraph();
18
- for (const [key, value] of Object.entries(args)) {
19
- this[key] = value;
23
+ this.loadArgs(args);
24
+ }
25
+
26
+ /**
27
+ * Loads the provided arguments.
28
+ * @throws {MissingAttributes} Thrown when required attr is not present.
29
+ * @param {Object} args
30
+ */
31
+ loadArgs (args) {
32
+ const expectedAttributes = ["name"];
33
+ if (typeof args !== "object" || args === null || Array.isArray(args)) {
34
+ // Not an object, so all attributes are missing.
35
+ throw new MissingAttributes("Engine", expectedAttributes);
20
36
  }
37
+ expectedAttributes.forEach((attr) => {
38
+ if (!(attr in args)) {
39
+ throw new MissingAttributes("Engine", attr);
40
+ }
41
+ this[attr] = args[attr];
42
+ });
21
43
  }
22
44
 
23
45
  /**
@@ -43,9 +65,6 @@ export class DALEngine {
43
65
  * @returns {Participant}
44
66
  */
45
67
  createParticipant (args) {
46
- // TODO: Validate that the args have the necessary keys
47
- // and raise custom error if they are missing.
48
- // Perhaps it is better to do that in the class itself.
49
68
  return new Participant(args);
50
69
  }
51
70
 
@@ -55,8 +74,6 @@ export class DALEngine {
55
74
  * @returns {Behavior}
56
75
  */
57
76
  createBehavior (args) {
58
- // TODO: Validate that the args have the necessary keys
59
- // and raise custom error if they are missing.
60
77
  return new Behavior(args);
61
78
  }
62
79
 
@@ -66,8 +83,43 @@ export class DALEngine {
66
83
  * @returns {Invariant}
67
84
  */
68
85
  createInvariant (args) {
69
- // TODO: Validate that the args have the necessary keys
70
- // and raise custom error if they are missing.
71
86
  return new Invariant(args);
72
87
  }
88
+
89
+
90
+ /**
91
+ * Returns the node in the graph with the given behavior name.
92
+ * @param {String} behaviorId
93
+ * @returns {GraphNode}
94
+ */
95
+ getNode (behaviorId) {
96
+ return this.graph.findNode(behaviorId);
97
+ }
98
+
99
+ /**
100
+ * Adds a node to the graph with the given behaviorId and goToBehaviors.
101
+ * @param {String} behaviorId
102
+ * @param {Array} goToBehaviorsIds
103
+ * @returns {GraphNode}
104
+ */
105
+ addNode (behaviorId, goToBehaviorsIds) {
106
+ const behavior = this.createBehavior({name: behaviorId});
107
+ return this.graph.addNode(behavior, goToBehaviorsIds);
108
+ }
109
+
110
+ /**
111
+ * Adds a goToBehavior to the node with the given behaviorId.
112
+ * @param {String} behaviorId
113
+ * @param {String|Array} goToBehaviorIds
114
+ * @returns {GraphNode}
115
+ */
116
+ addGoToBehavior (behaviorId, goToBehaviorIds) {
117
+ const node = this.graph.findNode(behaviorId);
118
+ if (Array.isArray(goToBehaviorIds)) {
119
+ node.goToBehaviorsIds.push(...goToBehaviorIds);
120
+ } else {
121
+ node.goToBehaviorsIds.push(goToBehaviorIds);
122
+ }
123
+ return node;
124
+ }
73
125
  }
@@ -0,0 +1,15 @@
1
+ import DALEngineError from "./DALEngineError";
2
+
3
+ class MissingAttributes extends DALEngineError {
4
+ constructor (type, attribute) {
5
+ let msg;
6
+ if (Array.isArray(attribute) && attribute.length > 1) {
7
+ msg = `"${type}" must be initialized with the attributes "${attribute}".`
8
+ } else {
9
+ msg = `"${type}" must be initialized with the attribute "${attribute}".`
10
+ }
11
+ super(msg);
12
+ }
13
+ }
14
+
15
+ export default MissingAttributes;