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/src/Members/Behavior.js
CHANGED
|
@@ -18,9 +18,9 @@ class Behavior extends Base {
|
|
|
18
18
|
this.abstractionIds = [];
|
|
19
19
|
this.invalidWorldState = false;
|
|
20
20
|
if (typeof args === "object" && Object.hasOwn(args, "uid")) {
|
|
21
|
-
this.
|
|
21
|
+
this._loadBehaviorFromJSON(args);
|
|
22
22
|
} else {
|
|
23
|
-
this.
|
|
23
|
+
this._loadArgs(args);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -29,7 +29,7 @@ class Behavior extends Base {
|
|
|
29
29
|
* @throws {MissingAttributes} Thrown when required attr is not present.
|
|
30
30
|
* @param {Object} args
|
|
31
31
|
*/
|
|
32
|
-
|
|
32
|
+
_loadArgs (args) {
|
|
33
33
|
const expectedAttributes = ["name"];
|
|
34
34
|
if (typeof args !== "object" || args === null || Array.isArray(args)) {
|
|
35
35
|
// Not an object, so all attributes are missing.
|
|
@@ -47,7 +47,7 @@ class Behavior extends Base {
|
|
|
47
47
|
* Loads the behavior from a JSON object.
|
|
48
48
|
* @param {Object} behaviorJSON
|
|
49
49
|
*/
|
|
50
|
-
|
|
50
|
+
_loadBehaviorFromJSON (behaviorJSON) {
|
|
51
51
|
for (const [key, value] of Object.entries(behaviorJSON)) {
|
|
52
52
|
if (key === "participants") {
|
|
53
53
|
value.forEach(node => this.participants.push(new Participant(node)));
|
|
@@ -62,7 +62,7 @@ class Behavior extends Base {
|
|
|
62
62
|
* @param {Participant} participant
|
|
63
63
|
* @returns
|
|
64
64
|
*/
|
|
65
|
-
|
|
65
|
+
addParticipant (participant) {
|
|
66
66
|
this.participants.push(participant);
|
|
67
67
|
return participant;
|
|
68
68
|
}
|
package/src/Members/Invariant.js
CHANGED
|
@@ -18,9 +18,9 @@ class Invariant extends Base {
|
|
|
18
18
|
this.invariantType = null;
|
|
19
19
|
this.traceId = null;
|
|
20
20
|
if (typeof args === "object" && Object.hasOwn(args, "uid")) {
|
|
21
|
-
this.
|
|
21
|
+
this._loadInvariantFromJSON(args);
|
|
22
22
|
} else {
|
|
23
|
-
this.
|
|
23
|
+
this._loadArgs(args);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -29,7 +29,7 @@ class Invariant extends Base {
|
|
|
29
29
|
* @throws {MissingAttributes} Thrown when required attr is not present.
|
|
30
30
|
* @param {Object} args
|
|
31
31
|
*/
|
|
32
|
-
|
|
32
|
+
_loadArgs (args) {
|
|
33
33
|
const expectedAttributes = ["name", "rule"];
|
|
34
34
|
if (typeof args !== "object" || args === null || Array.isArray(args)) {
|
|
35
35
|
// Not an object, so all attributes are missing.
|
|
@@ -47,7 +47,7 @@ class Invariant extends Base {
|
|
|
47
47
|
* Loads the participant from a JSON object.
|
|
48
48
|
* @param {Object} invariantJSON
|
|
49
49
|
*/
|
|
50
|
-
|
|
50
|
+
_loadInvariantFromJSON (invariantJSON) {
|
|
51
51
|
for (const [key, value] of Object.entries(invariantJSON)) {
|
|
52
52
|
this[key] = value;
|
|
53
53
|
};
|
|
@@ -14,14 +14,14 @@ class Participant extends Base {
|
|
|
14
14
|
*/
|
|
15
15
|
constructor (args) {
|
|
16
16
|
super();
|
|
17
|
-
this.type = ENGINE_TYPES.
|
|
17
|
+
this.type = ENGINE_TYPES.PARTICIPANT;
|
|
18
18
|
this.invariants = [];
|
|
19
19
|
this.abstractionId = null;
|
|
20
20
|
this.invariantViolated = false;
|
|
21
21
|
if (typeof args === "object" && Object.hasOwn(args, "uid")) {
|
|
22
|
-
this.
|
|
22
|
+
this._loadParticipantFromJSON(args);
|
|
23
23
|
} else {
|
|
24
|
-
this.
|
|
24
|
+
this._loadArgs(args);
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -30,7 +30,7 @@ class Participant extends Base {
|
|
|
30
30
|
* @throws {MissingAttributes} Thrown when required attr is not present.
|
|
31
31
|
* @param {Object} args
|
|
32
32
|
*/
|
|
33
|
-
|
|
33
|
+
_loadArgs (args) {
|
|
34
34
|
const expectedAttributes = ["name"];
|
|
35
35
|
if (typeof args !== "object" || args === null || Array.isArray(args)) {
|
|
36
36
|
// Not an object, so all attributes are missing.
|
|
@@ -48,7 +48,7 @@ class Participant extends Base {
|
|
|
48
48
|
* Loads the participant from a JSON object.
|
|
49
49
|
* @param {Object} participantJSON
|
|
50
50
|
*/
|
|
51
|
-
|
|
51
|
+
_loadParticipantFromJSON (participantJSON) {
|
|
52
52
|
for (const [key, value] of Object.entries(participantJSON)) {
|
|
53
53
|
if (key === "invariants") {
|
|
54
54
|
value.forEach(node => this.invariants.push(new Invariant(node)));
|
package/tests/DALEngine.test.js
CHANGED
|
@@ -14,7 +14,8 @@ describe("DALEngine", () => {
|
|
|
14
14
|
expect(dalInstance.name).toBe("Library Manager");
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
it("throws on missing attributes", () => {
|
|
17
|
+
it(" throws on missing attributes", () => {
|
|
18
|
+
expect(() => {new DALEngine()}).toThrow(MissingAttributes);
|
|
18
19
|
const d = new DALEngine({name: "Library Manager"});
|
|
19
20
|
expect(() => {d.createBehavior()}).toThrow(MissingAttributes);
|
|
20
21
|
expect(() => {d.createBehavior({})}).toThrow(MissingAttributes);
|
|
@@ -26,67 +27,76 @@ describe("DALEngine", () => {
|
|
|
26
27
|
|
|
27
28
|
it("adds node to graph", () => {
|
|
28
29
|
const d = new DALEngine({name: "Library Manager"});
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const goToBehaviors = [behavior2];
|
|
32
|
-
|
|
33
|
-
const node = d.graph.addNode(behavior1, goToBehaviors)
|
|
30
|
+
const goToBehaviorIds = ["AddBookToBasket"];
|
|
31
|
+
const node = d.addNode("AcceptBookFromUser", goToBehaviorIds);
|
|
34
32
|
|
|
35
33
|
const nodeType = node.type;
|
|
36
34
|
expect(nodeType).toBe(ENGINE_TYPES.GRAPH_NODE);
|
|
37
|
-
expect(node.
|
|
38
|
-
expect(node.
|
|
39
|
-
|
|
40
|
-
const foundNode = d.graph.findNode("AcceptBookFromUser");
|
|
41
|
-
expect(foundNode).toStrictEqual(node);
|
|
35
|
+
expect(node.getBehavior().name).toStrictEqual("AcceptBookFromUser");
|
|
36
|
+
expect(node.getGoToBehaviors()).toStrictEqual(goToBehaviorIds);
|
|
42
37
|
});
|
|
43
38
|
|
|
44
39
|
it("find node that was added using behavior name", () => {
|
|
45
40
|
const d = new DALEngine({name: "Library Manager"});
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
const node = d.addNode("AcceptBookFromUser", []);
|
|
42
|
+
|
|
43
|
+
expect(() => {d.getNode("AcceptBookFrmUser")}).toThrow(UnknownBehaviorError);
|
|
49
44
|
|
|
50
|
-
const foundNode = d.
|
|
45
|
+
const foundNode = d.getNode("AcceptBookFromUser");
|
|
51
46
|
expect(foundNode).toStrictEqual(node);
|
|
52
47
|
});
|
|
53
48
|
|
|
49
|
+
it("adds node to graph and removes it", () => {
|
|
50
|
+
const d = new DALEngine({name: "Library Manager"});
|
|
51
|
+
d.addNode("AcceptBookFromUser", []);
|
|
52
|
+
d.addNode("AddBookToBasket", []);
|
|
53
|
+
|
|
54
|
+
d.getNode("AcceptBookFromUser").addGoToBehavior("AddBookToBasket");
|
|
55
|
+
|
|
56
|
+
const node = d.getNode("AcceptBookFromUser");
|
|
57
|
+
|
|
58
|
+
const nodeType = node.type;
|
|
59
|
+
expect(nodeType).toBe(ENGINE_TYPES.GRAPH_NODE);
|
|
60
|
+
expect(node.getBehavior().name).toStrictEqual("AcceptBookFromUser");
|
|
61
|
+
expect(node.getGoToBehaviors()).toStrictEqual(["AddBookToBasket"]);
|
|
62
|
+
});
|
|
63
|
+
|
|
54
64
|
it("find node and check if observed behavior is valid transition", () => {
|
|
55
65
|
const d = new DALEngine({name: "Library Manager"});
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
const node1 = d.addNode("AcceptBookFromUser", []);
|
|
67
|
+
const node2 = d.addNode("AddBookToBasket", []);
|
|
68
|
+
d.addNode("AnotherBehavior", []);
|
|
69
|
+
|
|
70
|
+
node1.addGoToBehavior("AddBookToBasket");
|
|
71
|
+
node2.addGoToBehavior("AnotherBehavior");
|
|
62
72
|
|
|
63
73
|
// Misspell behavior name to trigger unknown behavior error
|
|
64
74
|
expect(() => {
|
|
65
|
-
d.
|
|
75
|
+
d.setCurrentBehavior("AcceptBookromUser");
|
|
66
76
|
}).toThrow(UnknownBehaviorError);
|
|
67
77
|
|
|
68
|
-
d.
|
|
69
|
-
expect(d.graph.currentNode
|
|
78
|
+
d.setCurrentBehavior("AcceptBookFromUser");
|
|
79
|
+
expect(d.graph.currentNode).toBe(node1);
|
|
70
80
|
|
|
71
|
-
d.
|
|
72
|
-
expect(d.graph.currentNode
|
|
81
|
+
d.goToBehavior("AddBookToBasket")
|
|
82
|
+
expect(d.graph.currentNode).toBe(node2);
|
|
73
83
|
|
|
74
84
|
// Reset current behavior so transition is valid
|
|
75
|
-
d.
|
|
76
|
-
d.
|
|
77
|
-
expect(d.graph.currentNode
|
|
85
|
+
d.setCurrentBehavior("AcceptBookFromUser");
|
|
86
|
+
d.goToBehavior("AddBookToBasket")
|
|
87
|
+
expect(d.graph.currentNode).toBe(node2);
|
|
78
88
|
|
|
79
89
|
// Raises error because current behavior is "AnotherBehavior"
|
|
80
90
|
// and it does not transition to itself.
|
|
81
91
|
expect(() => {
|
|
82
|
-
d.
|
|
92
|
+
d.goToBehavior("AddBookToBasket")
|
|
83
93
|
}).toThrow(InvalidTransitionError);
|
|
84
94
|
|
|
85
95
|
// Reset the current behavior and then go to a behavior
|
|
86
96
|
// which is misspelled and expect an invalid transition error
|
|
87
97
|
expect(() => {
|
|
88
|
-
d.
|
|
89
|
-
d.
|
|
98
|
+
d.setCurrentBehavior("AcceptBookFromUser");
|
|
99
|
+
d.goToBehavior("AddBookToasket")
|
|
90
100
|
}).toThrow(InvalidTransitionError);
|
|
91
101
|
});
|
|
92
102
|
|
|
@@ -125,13 +135,15 @@ describe("DALEngine", () => {
|
|
|
125
135
|
);
|
|
126
136
|
book.addInvariant(invariant);
|
|
127
137
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
d.
|
|
134
|
-
d.
|
|
138
|
+
|
|
139
|
+
d.addNode("AcceptBookFromUser", []);
|
|
140
|
+
d.addNode("AddBookToBasket", []);
|
|
141
|
+
d.addNode("AnotherBehavior", []);
|
|
142
|
+
|
|
143
|
+
d.getNode("AcceptBookFromUser").addGoToBehavior("AddBookToBasket");
|
|
144
|
+
d.getNode("AcceptBookFromUser").addGoToBehavior("AnotherBehavior");
|
|
145
|
+
|
|
146
|
+
d.getNode("AcceptBookFromUser").getBehavior().addParticipant(book);
|
|
135
147
|
|
|
136
148
|
const filePath = resolve(__dirname, "./temp/inspectSerializeTemp.json")
|
|
137
149
|
await writeFile(filePath, d.serialize())
|
package/tests/Invariant.test.js
CHANGED
|
@@ -72,28 +72,27 @@ describe("invariantTests", () => {
|
|
|
72
72
|
));
|
|
73
73
|
|
|
74
74
|
// Create behavior and participant
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
d.graph.addNode(behavior1, []);
|
|
75
|
+
const node1 = d.addNode("AcceptBookFromUser", []);
|
|
76
|
+
node1.getBehavior().addParticipant(book);
|
|
78
77
|
|
|
79
78
|
// Add value that respects invariant and expect valid world state
|
|
80
|
-
|
|
79
|
+
node1.getBehavior().setParticipantValue("book", {
|
|
81
80
|
"uid": 1,
|
|
82
81
|
"value": {
|
|
83
82
|
"name": "Harry Potter and Chamber of Secrets",
|
|
84
83
|
},
|
|
85
84
|
})
|
|
86
|
-
expect(
|
|
85
|
+
expect(node1.getBehavior().invalidWorldState).toBe(false);
|
|
87
86
|
|
|
88
87
|
|
|
89
88
|
// Add value that violates invariant and expect invalid world state
|
|
90
|
-
|
|
89
|
+
node1.getBehavior().setParticipantValue("book", {
|
|
91
90
|
"uid": 1,
|
|
92
91
|
"value": {
|
|
93
92
|
"name": "",
|
|
94
93
|
},
|
|
95
94
|
})
|
|
96
|
-
expect(
|
|
95
|
+
expect(node1.getBehavior().invalidWorldState).toBe(true);
|
|
97
96
|
|
|
98
97
|
// Write to file for inspection
|
|
99
98
|
const filePath = resolve(__dirname, "./temp/invariantBehaviorTemp.json")
|
|
@@ -8,31 +8,24 @@ describe("SimpleDesignTest", () => {
|
|
|
8
8
|
|
|
9
9
|
it("create simple design", async () => {
|
|
10
10
|
const d = new DALEngine({name: "Library Manager"});
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
d.
|
|
14
|
-
|
|
15
|
-
d.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
d.
|
|
20
|
-
|
|
21
|
-
d.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
d.graph.addNode(GetBookFromBasket, [GetFirstLetterOfBookName]);
|
|
30
|
-
const CreateSlotOnBookShelf = d.createBehavior({name: "CreateSlotOnBookShelf"});
|
|
31
|
-
const AddBookToShelf = d.createBehavior({name: "AddBookToShelf"});
|
|
32
|
-
d.graph.addNode(GetFirstLetterOfBookName, [CreateSlotOnBookShelf]);
|
|
33
|
-
d.graph.addNode(GetFirstLetterOfBookName, [AddBookToShelf]);
|
|
34
|
-
d.graph.addNode(CreateSlotOnBookShelf, [AddBookToShelf]);
|
|
35
|
-
d.graph.addNode(AddBookToShelf, [GetBookFromBasket]);
|
|
11
|
+
d.addNode("AcceptChoiceToAddBookToBasket", ["AcceptBookFromUser"]);
|
|
12
|
+
d.addNode("AcceptBookFromUser", ["AddBookToBasket"]);
|
|
13
|
+
d.addNode("AddBookToBasket", []);
|
|
14
|
+
d.addNode("AcceptChoiceToAuditLibrary", ["GenerateAuditReport"]);
|
|
15
|
+
d.addNode("GenerateAuditReport", ["HandAuditToUser"]);
|
|
16
|
+
d.addNode("HandAuditToUser", []);
|
|
17
|
+
|
|
18
|
+
d.addNode("AcceptChoiceToPlaceBooksOnShelf", ["GetBookFromBasket"]);
|
|
19
|
+
d.addNode("GetBookFromBasket", ["GetFirstLetterOfBookName"]);
|
|
20
|
+
d.addNode("GetFirstLetterOfBookName", ["CreateSlotOnBookShelf", "AddBookToShelf"]);
|
|
21
|
+
d.addNode("CreateSlotOnBookShelf", ["AddBookToShelf"]);
|
|
22
|
+
d.addNode("AddBookToShelf", ["GetBookFromBasket"]);
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
d.removeNode("GetBookFromBasket");
|
|
26
|
+
|
|
27
|
+
const filePath = resolve(__dirname, "./temp/simple_design_temp.json")
|
|
28
|
+
await writeFile(filePath, d.serialize())
|
|
36
29
|
|
|
37
30
|
// Output can be viewed using https://mermaid.live/
|
|
38
31
|
const filePath2 = resolve(__dirname, "./temp/simple_design_mermaid.txt")
|