Skip to content

Commit 4aa0e7e

Browse files
committed
correct evaluate node and graph computation
1 parent e2e18ed commit 4aa0e7e

File tree

6 files changed

+176
-165
lines changed

6 files changed

+176
-165
lines changed

src/components/molecules/flow/graph/Graph.js

Lines changed: 6 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import Operators from '../constants/operators.js';
2-
31
// assumption is that apis are giving json as output
42

3+
import { computeEvaluateNode } from './compute/evaluatenode';
4+
import { computeRequestNode } from './compute/requestnode';
5+
56
class Graph {
67
constructor(nodes, edges, onGraphComplete) {
78
this.nodes = nodes;
@@ -18,165 +19,6 @@ class Graph {
1819
return Date.now() - this.startTime > this.timeout;
1920
}
2021

21-
#formulateRequest(node, finalUrl) {
22-
let restMethod = node.data.requestType.toLowerCase();
23-
let contentType = 'application/json';
24-
let requestData = undefined;
25-
26-
if (restMethod === 'get') {
27-
if (node.data.requestBody) {
28-
if (node.data.requestBody.type === 'raw-json') {
29-
contentType = 'application/json';
30-
requestData = node.data.requestBody.body ? JSON.parse(node.data.requestBody.body) : JSON.parse('{}');
31-
}
32-
}
33-
} else if (restMethod === 'post' || restMethod === 'put') {
34-
if (node.data.requestBody) {
35-
if (node.data.requestBody.type === 'form-data') {
36-
contentType = 'multipart/form-data';
37-
requestData = {
38-
key: node.data.requestBody.body.key,
39-
value: node.data.requestBody.body.value,
40-
name: node.data.requestBody.body.name,
41-
};
42-
} else if (node.data.requestBody.type === 'raw-json') {
43-
contentType = 'application/json';
44-
requestData = node.data.requestBody.body ? JSON.parse(node.data.requestBody.body) : JSON.parse('{}');
45-
}
46-
}
47-
}
48-
49-
const options = {
50-
method: restMethod,
51-
url: finalUrl,
52-
headers: {
53-
'Content-type': contentType,
54-
},
55-
data: requestData,
56-
};
57-
58-
if (this.auth.type === 'basic-auth') {
59-
options.auth = {};
60-
options.auth.username = this.auth.username;
61-
options.auth.password = this.auth.password;
62-
}
63-
64-
this.logs.push(`${restMethod} ${finalUrl}`);
65-
return options;
66-
}
67-
68-
#computeNodeVariable(variable, prevNodeOutputData) {
69-
if (variable.type.toLowerCase() === 'string') {
70-
return variable.value;
71-
}
72-
73-
if (variable.type.toLowerCase() === 'number') {
74-
return variable.value;
75-
}
76-
77-
if (variable.type.toLowerCase() === 'bool') {
78-
return Boolean(variable.value);
79-
}
80-
81-
if (variable.type.toLowerCase() === 'select') {
82-
if (prevNodeOutputData == undefined || Object.keys(prevNodeOutputData).length === 0) {
83-
this.logs.push(
84-
`Cannot evaluate variable ${variable} as previous node output data ${JSON.stringify(prevNodeOutputData)} is empty`,
85-
);
86-
throw 'Error evaluating node variables';
87-
}
88-
const jsonTree = variable.value.split('.');
89-
const getVal = (parent, pos) => {
90-
if (pos == jsonTree.length) {
91-
return parent;
92-
}
93-
const key = jsonTree[pos];
94-
if (key == '') {
95-
return parent;
96-
}
97-
98-
return getVal(parent[key], pos + 1);
99-
};
100-
const result = getVal(prevNodeOutputData, 0);
101-
if (result == undefined) {
102-
this.logs.push(
103-
`Cannot evaluate variable ${JSON.stringify(variable)} as previous node output data ${JSON.stringify(prevNodeOutputData)} did not contain the variable`,
104-
);
105-
throw 'Error evaluating node variables';
106-
}
107-
return result;
108-
}
109-
}
110-
111-
#computeNodeVariables(variables, prevNodeOutputData) {
112-
let evalVariables = {};
113-
Object.entries(variables).map(([vname, variable], index) => {
114-
evalVariables[vname] = this.#computeNodeVariable(variable, prevNodeOutputData);
115-
});
116-
return evalVariables;
117-
}
118-
119-
#runHttpRequest(request) {
120-
const { ipcRenderer } = window;
121-
122-
return new Promise((resolve, reject) => {
123-
ipcRenderer.invoke('renderer:run-http-request', request).then(resolve).catch(reject);
124-
});
125-
}
126-
127-
async #computeRequestNode(node, prevNodeOutputData) {
128-
// step1 evaluate variables of this node
129-
const evalVariables = this.#computeNodeVariables(node.data.variables, prevNodeOutputData);
130-
131-
// step2 replace variables in url with value
132-
let finalUrl = node.data.url;
133-
Object.entries(evalVariables).map(([vname, vvalue], index) => {
134-
finalUrl = finalUrl.replace(`{${vname}}`, vvalue);
135-
});
136-
137-
// step 3
138-
const options = this.#formulateRequest(node, finalUrl);
139-
140-
console.debug('Evaluated variables: ', evalVariables);
141-
console.debug('Evaluated Url: ', finalUrl);
142-
143-
const res = await this.#runHttpRequest(options);
144-
145-
if (res.error) {
146-
console.debug('Failure at node: ', node);
147-
console.debug('Error encountered: ', JSON.stringify(res.error));
148-
this.logs.push(`Request failed: ${JSON.stringify(res.error)}`);
149-
return ['Failed', node, res.error];
150-
} else {
151-
this.logs.push(`Request successful: ${JSON.stringify(res)}`);
152-
console.debug('Response: ', JSON.stringify(res));
153-
return ['Success', node, res];
154-
}
155-
}
156-
157-
#computeEvaluateNode(node, prevNodeOutputData) {
158-
const evalVariables = this.#computeNodeVariables(node.data.variables, prevNodeOutputData);
159-
const var1 = evalVariables.var1;
160-
const var2 = evalVariables.var2;
161-
162-
const operator = node.data.operator;
163-
if (operator == undefined) {
164-
throw 'Operator undefined';
165-
}
166-
this.logs.push(
167-
`Evaluate var1: ${JSON.stringify(var1)} of type: ${typeof var1}, var2: ${JSON.stringify(var2)} of type: ${typeof var2} with operator: ${operator}`,
168-
);
169-
if (operator == Operators.isEqualTo) {
170-
return var1 === var2;
171-
} else if (operator == Operators.isNotEqualTo) {
172-
return var1 != var2;
173-
} else if (operator == Operators.isGreaterThan) {
174-
return var1 > var2;
175-
} else if (operator == Operators.isLessThan) {
176-
return var1 < var2;
177-
}
178-
}
179-
18022
#computeConnectingEdge(node, result) {
18123
let connectingEdge = undefined;
18224

@@ -225,7 +67,7 @@ class Graph {
22567
}
22668

22769
if (node.type === 'evaluateNode') {
228-
if (this.#computeEvaluateNode(node, prevNodeOutputData)) {
70+
if (computeEvaluateNode(node, prevNodeOutputData, this.logs)) {
22971
this.logs.push('Result: true');
23072
result = ['Success', node, prevNodeOutput, true];
23173
} else {
@@ -250,7 +92,7 @@ class Graph {
25092
}
25193

25294
if (node.type === 'requestNode') {
253-
result = await this.#computeRequestNode(node, prevNodeOutputData);
95+
result = await computeRequestNode(node, prevNodeOutputData, this.auth, this.logs);
25496
}
25597

25698
if (this.#checkTimeout()) {
@@ -308,6 +150,7 @@ class Graph {
308150
}
309151
this.logs.push('End Flowtest');
310152
this.logs.push(`Total time: ${Date.now() - this.startTime} ms`);
153+
console.log(this.logs);
311154
this.onGraphComplete(result, this.logs);
312155
});
313156
} else {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Operators from '../../constants/operators';
2+
import { computeNodeVariables } from './utils';
3+
4+
export const computeEvaluateNode = (node, prevNodeOutputData, logs) => {
5+
const evalVariables = computeNodeVariables(node.data.variables, prevNodeOutputData);
6+
const var1 = evalVariables.var1;
7+
const var2 = evalVariables.var2;
8+
9+
const operator = node.data.operator;
10+
if (operator == undefined) {
11+
throw 'Operator undefined';
12+
}
13+
logs.push(
14+
`Evaluate var1: ${JSON.stringify(var1)} of type: ${typeof var1}, var2: ${JSON.stringify(var2)} of type: ${typeof var2} with operator: ${operator}`,
15+
);
16+
if (operator == Operators.isEqualTo) {
17+
return var1 === var2;
18+
} else if (operator == Operators.isNotEqualTo) {
19+
return var1 != var2;
20+
} else if (operator == Operators.isGreaterThan) {
21+
return var1 > var2;
22+
} else if (operator == Operators.isLessThan) {
23+
return var1 < var2;
24+
}
25+
};
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { computeNodeVariables } from './utils';
2+
3+
const runHttpRequest = (request) => {
4+
const { ipcRenderer } = window;
5+
6+
return new Promise((resolve, reject) => {
7+
ipcRenderer.invoke('renderer:run-http-request', request).then(resolve).catch(reject);
8+
});
9+
};
10+
11+
const formulateRequest = (node, finalUrl, auth, logs) => {
12+
let restMethod = node.data.requestType.toLowerCase();
13+
let contentType = 'application/json';
14+
let requestData = undefined;
15+
16+
if (restMethod === 'get') {
17+
if (node.data.requestBody) {
18+
if (node.data.requestBody.type === 'raw-json') {
19+
contentType = 'application/json';
20+
requestData = node.data.requestBody.body ? JSON.parse(node.data.requestBody.body) : JSON.parse('{}');
21+
}
22+
}
23+
} else if (restMethod === 'post' || restMethod === 'put') {
24+
if (node.data.requestBody) {
25+
if (node.data.requestBody.type === 'form-data') {
26+
contentType = 'multipart/form-data';
27+
requestData = {
28+
key: node.data.requestBody.body.key,
29+
value: node.data.requestBody.body.value,
30+
name: node.data.requestBody.body.name,
31+
};
32+
} else if (node.data.requestBody.type === 'raw-json') {
33+
contentType = 'application/json';
34+
requestData = node.data.requestBody.body ? JSON.parse(node.data.requestBody.body) : JSON.parse('{}');
35+
}
36+
}
37+
}
38+
39+
const options = {
40+
method: restMethod,
41+
url: finalUrl,
42+
headers: {
43+
'Content-type': contentType,
44+
},
45+
data: requestData,
46+
};
47+
48+
if (auth.type === 'basic-auth') {
49+
options.auth = {};
50+
options.auth.username = auth.username;
51+
options.auth.password = auth.password;
52+
}
53+
54+
logs.push(`${restMethod} ${finalUrl}`);
55+
return options;
56+
};
57+
58+
export const computeRequestNode = async (node, prevNodeOutputData, auth, logs) => {
59+
// step1 evaluate variables of this node
60+
const evalVariables = computeNodeVariables(node.data.variables, prevNodeOutputData);
61+
62+
// step2 replace variables in url with value
63+
let finalUrl = node.data.url;
64+
Object.entries(evalVariables).map(([vname, vvalue], index) => {
65+
finalUrl = finalUrl.replace(`{${vname}}`, vvalue);
66+
});
67+
68+
// step 3
69+
const options = formulateRequest(node, finalUrl, auth, logs);
70+
71+
console.debug('Evaluated variables: ', evalVariables);
72+
console.debug('Evaluated Url: ', finalUrl);
73+
74+
const res = await runHttpRequest(options);
75+
76+
if (res.error) {
77+
console.debug('Failure at node: ', node);
78+
console.debug('Error encountered: ', JSON.stringify(res.error));
79+
logs.push(`Request failed: ${JSON.stringify(res.error)}`);
80+
return ['Failed', node, res.error];
81+
} else {
82+
logs.push(`Request successful: ${JSON.stringify(res)}`);
83+
console.debug('Response: ', JSON.stringify(res));
84+
return ['Success', node, res];
85+
}
86+
};
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const computeNodeVariable = (variable, prevNodeOutputData) => {
2+
if (variable.type.toLowerCase() === 'string') {
3+
return variable.value;
4+
}
5+
6+
if (variable.type.toLowerCase() === 'number') {
7+
return variable.value;
8+
}
9+
10+
if (variable.type.toLowerCase() === 'bool') {
11+
return Boolean(variable.value);
12+
}
13+
14+
if (variable.type.toLowerCase() === 'select') {
15+
try {
16+
if (prevNodeOutputData == undefined || Object.keys(prevNodeOutputData).length === 0) {
17+
console.debug(
18+
`Cannot evaluate variable ${variable} as previous node output data ${JSON.stringify(prevNodeOutputData)} is empty`,
19+
);
20+
throw `Cannot evaluate variable ${variable.value}`;
21+
}
22+
const jsonTree = variable.value.split('.');
23+
const getVal = (parent, pos) => {
24+
if (pos == jsonTree.length) {
25+
return parent;
26+
}
27+
const key = jsonTree[pos];
28+
if (key == '') {
29+
return parent;
30+
}
31+
32+
return getVal(parent[key], pos + 1);
33+
};
34+
const result = getVal(prevNodeOutputData, 0);
35+
if (result == undefined) {
36+
console.debug(
37+
`Cannot evaluate variable ${JSON.stringify(variable)} as previous node output data ${JSON.stringify(prevNodeOutputData)} did not contain the variable`,
38+
);
39+
throw `Cannot evaluate variable ${variable.value}`;
40+
}
41+
return result;
42+
} catch (error) {
43+
throw `Cannot evaluate variable ${variable.value}`;
44+
}
45+
}
46+
};
47+
48+
export const computeNodeVariables = (variables, prevNodeOutputData) => {
49+
let evalVariables = {};
50+
Object.entries(variables).map(([vname, variable], index) => {
51+
evalVariables[vname] = computeNodeVariable(variable, prevNodeOutputData);
52+
});
53+
return evalVariables;
54+
};

0 commit comments

Comments
 (0)