dal-engine-core-js-lib-dev 0.0.1 → 0.0.3
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.cjs +158 -48
- package/dist/index.esm.js +158 -48
- package/package.json +1 -1
- package/src/BehavioralControlGraph/BehavioralControlGraph.js +15 -15
- package/src/BehavioralControlGraph/GraphNode.js +55 -15
- package/src/DALEngine.js +75 -4
- package/src/Members/Behavior.js +5 -5
- package/src/Members/Invariant.js +4 -4
- package/src/Members/Participant.js +5 -5
- package/tests/DALEngine.test.js +51 -39
- package/tests/Invariant.test.js +6 -7
- package/tests/SimpleDesign.test.js +18 -25
package/dist/index.cjs
CHANGED
|
@@ -82,9 +82,9 @@ class Invariant extends Base {
|
|
|
82
82
|
this.invariantType = null;
|
|
83
83
|
this.traceId = null;
|
|
84
84
|
if (typeof args === "object" && Object.hasOwn(args, "uid")) {
|
|
85
|
-
this.
|
|
85
|
+
this._loadInvariantFromJSON(args);
|
|
86
86
|
} else {
|
|
87
|
-
this.
|
|
87
|
+
this._loadArgs(args);
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -93,7 +93,7 @@ class Invariant extends Base {
|
|
|
93
93
|
* @throws {MissingAttributes} Thrown when required attr is not present.
|
|
94
94
|
* @param {Object} args
|
|
95
95
|
*/
|
|
96
|
-
|
|
96
|
+
_loadArgs (args) {
|
|
97
97
|
const expectedAttributes = ["name", "rule"];
|
|
98
98
|
if (typeof args !== "object" || args === null || Array.isArray(args)) {
|
|
99
99
|
// Not an object, so all attributes are missing.
|
|
@@ -111,7 +111,7 @@ class Invariant extends Base {
|
|
|
111
111
|
* Loads the participant from a JSON object.
|
|
112
112
|
* @param {Object} invariantJSON
|
|
113
113
|
*/
|
|
114
|
-
|
|
114
|
+
_loadInvariantFromJSON (invariantJSON) {
|
|
115
115
|
for (const [key, value] of Object.entries(invariantJSON)) {
|
|
116
116
|
this[key] = value;
|
|
117
117
|
} // Reset these because they are set by the execution
|
|
@@ -198,14 +198,14 @@ class Participant extends Base {
|
|
|
198
198
|
*/
|
|
199
199
|
constructor (args) {
|
|
200
200
|
super();
|
|
201
|
-
this.type = ENGINE_TYPES$1.
|
|
201
|
+
this.type = ENGINE_TYPES$1.PARTICIPANT;
|
|
202
202
|
this.invariants = [];
|
|
203
203
|
this.abstractionId = null;
|
|
204
204
|
this.invariantViolated = false;
|
|
205
205
|
if (typeof args === "object" && Object.hasOwn(args, "uid")) {
|
|
206
|
-
this.
|
|
206
|
+
this._loadParticipantFromJSON(args);
|
|
207
207
|
} else {
|
|
208
|
-
this.
|
|
208
|
+
this._loadArgs(args);
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
|
|
@@ -214,7 +214,7 @@ class Participant extends Base {
|
|
|
214
214
|
* @throws {MissingAttributes} Thrown when required attr is not present.
|
|
215
215
|
* @param {Object} args
|
|
216
216
|
*/
|
|
217
|
-
|
|
217
|
+
_loadArgs (args) {
|
|
218
218
|
const expectedAttributes = ["name"];
|
|
219
219
|
if (typeof args !== "object" || args === null || Array.isArray(args)) {
|
|
220
220
|
// Not an object, so all attributes are missing.
|
|
@@ -232,7 +232,7 @@ class Participant extends Base {
|
|
|
232
232
|
* Loads the participant from a JSON object.
|
|
233
233
|
* @param {Object} participantJSON
|
|
234
234
|
*/
|
|
235
|
-
|
|
235
|
+
_loadParticipantFromJSON (participantJSON) {
|
|
236
236
|
for (const [key, value] of Object.entries(participantJSON)) {
|
|
237
237
|
if (key === "invariants") {
|
|
238
238
|
value.forEach(node => this.invariants.push(new Invariant(node)));
|
|
@@ -304,9 +304,9 @@ class Behavior extends Base {
|
|
|
304
304
|
this.abstractionIds = [];
|
|
305
305
|
this.invalidWorldState = false;
|
|
306
306
|
if (typeof args === "object" && Object.hasOwn(args, "uid")) {
|
|
307
|
-
this.
|
|
307
|
+
this._loadBehaviorFromJSON(args);
|
|
308
308
|
} else {
|
|
309
|
-
this.
|
|
309
|
+
this._loadArgs(args);
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
312
|
|
|
@@ -315,7 +315,7 @@ class Behavior extends Base {
|
|
|
315
315
|
* @throws {MissingAttributes} Thrown when required attr is not present.
|
|
316
316
|
* @param {Object} args
|
|
317
317
|
*/
|
|
318
|
-
|
|
318
|
+
_loadArgs (args) {
|
|
319
319
|
const expectedAttributes = ["name"];
|
|
320
320
|
if (typeof args !== "object" || args === null || Array.isArray(args)) {
|
|
321
321
|
// Not an object, so all attributes are missing.
|
|
@@ -333,7 +333,7 @@ class Behavior extends Base {
|
|
|
333
333
|
* Loads the behavior from a JSON object.
|
|
334
334
|
* @param {Object} behaviorJSON
|
|
335
335
|
*/
|
|
336
|
-
|
|
336
|
+
_loadBehaviorFromJSON (behaviorJSON) {
|
|
337
337
|
for (const [key, value] of Object.entries(behaviorJSON)) {
|
|
338
338
|
if (key === "participants") {
|
|
339
339
|
value.forEach(node => this.participants.push(new Participant(node)));
|
|
@@ -347,7 +347,7 @@ class Behavior extends Base {
|
|
|
347
347
|
* @param {Participant} participant
|
|
348
348
|
* @returns
|
|
349
349
|
*/
|
|
350
|
-
|
|
350
|
+
addParticipant (participant) {
|
|
351
351
|
this.participants.push(participant);
|
|
352
352
|
return participant;
|
|
353
353
|
}
|
|
@@ -387,13 +387,14 @@ class GraphNode extends Base {
|
|
|
387
387
|
constructor (args) {
|
|
388
388
|
super();
|
|
389
389
|
this.type = ENGINE_TYPES$1.GRAPH_NODE;
|
|
390
|
-
this.
|
|
390
|
+
this._behavior = null;
|
|
391
|
+
this._goToBehaviorIds = [];
|
|
391
392
|
if (typeof args === "object" && args !== null) {
|
|
392
393
|
if (Object.hasOwn(args, "uid")) {
|
|
393
|
-
this.
|
|
394
|
+
this._loadNodeFromJSON(args);
|
|
394
395
|
} else {
|
|
395
|
-
this.
|
|
396
|
-
this.
|
|
396
|
+
this._behavior = args.behavior;
|
|
397
|
+
this._goToBehaviorIds = args.goToBehaviorsIds;
|
|
397
398
|
}
|
|
398
399
|
}
|
|
399
400
|
}
|
|
@@ -402,29 +403,68 @@ class GraphNode extends Base {
|
|
|
402
403
|
* Loads the nodes from a JSON object.
|
|
403
404
|
* @param {Object} nodesJSON
|
|
404
405
|
*/
|
|
405
|
-
|
|
406
|
+
_loadNodeFromJSON (nodesJSON) {
|
|
406
407
|
for (const [key, value] of Object.entries(nodesJSON)) {
|
|
407
408
|
if (key === "behavior") {
|
|
408
|
-
this.
|
|
409
|
-
} else if (key === "
|
|
410
|
-
value.forEach(
|
|
409
|
+
this._behavior = new Behavior(value);
|
|
410
|
+
} else if (key === "goToBehaviorsIds") {
|
|
411
|
+
value.forEach(behaviorId => this._goToBehaviorIds.push(behaviorId));
|
|
411
412
|
} else {
|
|
412
413
|
this[key] = nodesJSON[key];
|
|
413
414
|
}
|
|
414
415
|
} }
|
|
415
416
|
|
|
417
|
+
/**
|
|
418
|
+
* Returns the behavior of the node.
|
|
419
|
+
* @returns {Behavior|Null}
|
|
420
|
+
*/
|
|
421
|
+
getBehavior () {
|
|
422
|
+
return this._behavior;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Returns the list of behavior names that this node transitions to.
|
|
427
|
+
* @returns {Array}
|
|
428
|
+
*/
|
|
429
|
+
getGoToBehaviors () {
|
|
430
|
+
return this._goToBehaviorIds;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Adds a behavior name to the list of behaviors that this
|
|
435
|
+
* node transitions to.
|
|
436
|
+
* @param {String} behaviorId ID of behavior.
|
|
437
|
+
*/
|
|
438
|
+
addGoToBehavior (behaviorId) {
|
|
439
|
+
this._goToBehaviorIds.push(behaviorId);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Adds a behavior name to the list of behaviors that this
|
|
444
|
+
* node transitions to.
|
|
445
|
+
* @param {Array} behaviorIds IDs of behaviors.
|
|
446
|
+
*/
|
|
447
|
+
addGoToBehaviors (behaviorIds) {
|
|
448
|
+
this._goToBehaviorIds.push(...behaviorIds);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
removeGoToBehavior (behaviorId) {
|
|
452
|
+
const goToIndex = this._goToBehaviorIds.indexOf(behaviorId);
|
|
453
|
+
if (goToIndex > -1) {
|
|
454
|
+
this._goToBehaviorIds.splice(goToIndex, 1);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
416
458
|
/**
|
|
417
459
|
* Checks if the provided behavior name is a valid
|
|
418
|
-
*
|
|
419
|
-
* result of the this nodes state transformation. i.e.
|
|
420
|
-
* is this behavior in the goToBehavior list.
|
|
460
|
+
* transition from this node.
|
|
421
461
|
* @param {String} behaviorName
|
|
422
462
|
* @returns {Boolean}
|
|
423
463
|
*/
|
|
424
|
-
|
|
425
|
-
for (let i = 0; i < this.
|
|
426
|
-
const
|
|
427
|
-
if (
|
|
464
|
+
isValidTransition (behaviorName) {
|
|
465
|
+
for (let i = 0; i < this._goToBehaviorIds.length; i++) {
|
|
466
|
+
const behaviorId = this._goToBehaviorIds[i];
|
|
467
|
+
if (behaviorId === behaviorName) {
|
|
428
468
|
return true;
|
|
429
469
|
}
|
|
430
470
|
}
|
|
@@ -447,7 +487,7 @@ class BehavioralControlGraph extends Base {
|
|
|
447
487
|
this.nodes = [];
|
|
448
488
|
if (typeof args === "object" && args !== null) {
|
|
449
489
|
if (Object.hasOwn(args, "uid")) {
|
|
450
|
-
this.
|
|
490
|
+
this._loadGraphFromJSON(args);
|
|
451
491
|
} else {
|
|
452
492
|
this.name = args.name;
|
|
453
493
|
}
|
|
@@ -458,7 +498,7 @@ class BehavioralControlGraph extends Base {
|
|
|
458
498
|
* Loads the graph from a JSON object..
|
|
459
499
|
* @param {Object} graphJson
|
|
460
500
|
*/
|
|
461
|
-
|
|
501
|
+
_loadGraphFromJSON (graphJson) {
|
|
462
502
|
for (const [key, value] of Object.entries(graphJson)) {
|
|
463
503
|
if (key === "nodes") {
|
|
464
504
|
value.forEach(node => this.nodes.push(new GraphNode(node)));
|
|
@@ -470,13 +510,13 @@ class BehavioralControlGraph extends Base {
|
|
|
470
510
|
/**
|
|
471
511
|
* Adds a node to the graph.
|
|
472
512
|
* @param {Behavior} behavior
|
|
473
|
-
* @param {Array}
|
|
513
|
+
* @param {Array} goToBehaviorsIds
|
|
474
514
|
* @returns
|
|
475
515
|
*/
|
|
476
|
-
|
|
516
|
+
_addNode (behavior, goToBehaviorsIds) {
|
|
477
517
|
const node = new GraphNode({
|
|
478
518
|
behavior: behavior,
|
|
479
|
-
|
|
519
|
+
goToBehaviorsIds: goToBehaviorsIds,
|
|
480
520
|
});
|
|
481
521
|
this.nodes.push(node);
|
|
482
522
|
return node;
|
|
@@ -490,9 +530,9 @@ class BehavioralControlGraph extends Base {
|
|
|
490
530
|
* does not exist in the graph.
|
|
491
531
|
* @returns
|
|
492
532
|
*/
|
|
493
|
-
|
|
533
|
+
_findNode (behaviorName) {
|
|
494
534
|
for (let i = 0; i < this.nodes.length; i++) {
|
|
495
|
-
const behavior = this.nodes[i].
|
|
535
|
+
const behavior = this.nodes[i].getBehavior();
|
|
496
536
|
if (behavior.name === behaviorName) {
|
|
497
537
|
return this.nodes[i];
|
|
498
538
|
}
|
|
@@ -509,8 +549,8 @@ class BehavioralControlGraph extends Base {
|
|
|
509
549
|
*
|
|
510
550
|
* @param {String} behaviorName
|
|
511
551
|
*/
|
|
512
|
-
|
|
513
|
-
const node = this.
|
|
552
|
+
_setCurrentBehavior (behaviorName) {
|
|
553
|
+
const node = this._findNode(behaviorName);
|
|
514
554
|
/**
|
|
515
555
|
* TODO: Ensure it is atomic because the execution
|
|
516
556
|
* will only set a behavior when its the first one.
|
|
@@ -526,11 +566,11 @@ class BehavioralControlGraph extends Base {
|
|
|
526
566
|
* @throws {InvalidTransitionError} Raised when the provided
|
|
527
567
|
* behavior is not a valid transition.
|
|
528
568
|
*/
|
|
529
|
-
|
|
530
|
-
if (this.currentNode.
|
|
531
|
-
this.currentNode = this.
|
|
569
|
+
_goToBehavior (nextBehaviorName) {
|
|
570
|
+
if (this.currentNode.isValidTransition(nextBehaviorName)) {
|
|
571
|
+
this.currentNode = this._findNode(nextBehaviorName);
|
|
532
572
|
} else {
|
|
533
|
-
throw new InvalidTransitionError(this.currentNode.
|
|
573
|
+
throw new InvalidTransitionError(this.currentNode.getBehavior().name, nextBehaviorName);
|
|
534
574
|
}
|
|
535
575
|
}
|
|
536
576
|
|
|
@@ -541,8 +581,8 @@ class BehavioralControlGraph extends Base {
|
|
|
541
581
|
exportAsMermaid () {
|
|
542
582
|
let mermaid = "flowchart TD\n";
|
|
543
583
|
this.nodes.forEach((node) => {
|
|
544
|
-
node.
|
|
545
|
-
mermaid += ` ${node.
|
|
584
|
+
node.getGoToBehaviors().forEach((behaviorId) => {
|
|
585
|
+
mermaid += ` ${node.getBehavior().name} --> ${behaviorId}\n`;
|
|
546
586
|
});
|
|
547
587
|
});
|
|
548
588
|
return mermaid;
|
|
@@ -565,9 +605,26 @@ class BehavioralControlGraph extends Base {
|
|
|
565
605
|
class DALEngine {
|
|
566
606
|
constructor (args) {
|
|
567
607
|
this.graph = new BehavioralControlGraph();
|
|
568
|
-
|
|
569
|
-
|
|
608
|
+
this.loadArgs(args);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Loads the provided arguments.
|
|
613
|
+
* @throws {MissingAttributes} Thrown when required attr is not present.
|
|
614
|
+
* @param {Object} args
|
|
615
|
+
*/
|
|
616
|
+
loadArgs (args) {
|
|
617
|
+
const expectedAttributes = ["name"];
|
|
618
|
+
if (typeof args !== "object" || args === null || Array.isArray(args)) {
|
|
619
|
+
// Not an object, so all attributes are missing.
|
|
620
|
+
throw new MissingAttributes("Engine", expectedAttributes);
|
|
570
621
|
}
|
|
622
|
+
expectedAttributes.forEach((attr) => {
|
|
623
|
+
if (!(attr in args)) {
|
|
624
|
+
throw new MissingAttributes("Engine", attr);
|
|
625
|
+
}
|
|
626
|
+
this[attr] = args[attr];
|
|
627
|
+
});
|
|
571
628
|
}
|
|
572
629
|
|
|
573
630
|
/**
|
|
@@ -583,8 +640,7 @@ class DALEngine {
|
|
|
583
640
|
* @param {String} jsonText
|
|
584
641
|
*/
|
|
585
642
|
deserialize (jsonText) {
|
|
586
|
-
this.graph = new BehavioralControlGraph();
|
|
587
|
-
this.graph.loadGraphFromJSON(JSON.parse(jsonText));
|
|
643
|
+
this.graph = new BehavioralControlGraph(JSON.parse(jsonText));
|
|
588
644
|
}
|
|
589
645
|
|
|
590
646
|
/**
|
|
@@ -613,6 +669,60 @@ class DALEngine {
|
|
|
613
669
|
createInvariant (args) {
|
|
614
670
|
return new Invariant(args);
|
|
615
671
|
}
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Returns the node in the graph with the given behavior name.
|
|
676
|
+
* @param {String} behaviorId
|
|
677
|
+
* @returns {GraphNode}
|
|
678
|
+
*/
|
|
679
|
+
getNode (behaviorId) {
|
|
680
|
+
return this.graph._findNode(behaviorId);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* Adds a node to the graph with the given behaviorId and goToBehaviors.
|
|
685
|
+
* @param {String} behaviorId
|
|
686
|
+
* @param {Array} goToBehaviorsIds
|
|
687
|
+
* @returns {GraphNode}
|
|
688
|
+
*/
|
|
689
|
+
addNode (behaviorId, goToBehaviorsIds) {
|
|
690
|
+
const behavior = this.createBehavior({name: behaviorId});
|
|
691
|
+
const goToIds = goToBehaviorsIds?goToBehaviorsIds:[];
|
|
692
|
+
return this.graph._addNode(behavior, goToIds);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Deletes a node from the graph with the given behaviorId and
|
|
697
|
+
* removes it from the goToBehavior list of all other nodes.
|
|
698
|
+
* @param {String} behaviorId
|
|
699
|
+
*/
|
|
700
|
+
removeNode (behaviorId) {
|
|
701
|
+
const node = this.graph._findNode(behaviorId);
|
|
702
|
+
const nodeIndex = this.graph.nodes.indexOf(node);
|
|
703
|
+
this.graph.nodes.splice(nodeIndex, 1);
|
|
704
|
+
for (const node of this.graph.nodes) {
|
|
705
|
+
node.removeGoToBehavior(behaviorId);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Sets the current behavior in the graph.
|
|
711
|
+
* @param {String} behaviorId
|
|
712
|
+
*/
|
|
713
|
+
setCurrentBehavior (behaviorId) {
|
|
714
|
+
this.graph._setCurrentBehavior(behaviorId);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* Transitions the graph to the given behavior if it
|
|
720
|
+
* is a valid transition from the current behavior.
|
|
721
|
+
* @param {String} nextBehaviorId ID of the next behavior.
|
|
722
|
+
*/
|
|
723
|
+
goToBehavior (nextBehaviorId) {
|
|
724
|
+
this.graph._goToBehavior(nextBehaviorId);
|
|
725
|
+
}
|
|
616
726
|
}
|
|
617
727
|
|
|
618
728
|
exports.DALEngine = DALEngine;
|