@blokjs/if-else 0.2.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/CHANGELOG.md +251 -0
- package/README.md +42 -0
- package/config.json +116 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/inputSchema.d.ts +35 -0
- package/dist/inputSchema.js +36 -0
- package/dist/inputSchema.js.map +1 -0
- package/dist/test/index.test.d.ts +7 -0
- package/dist/test/index.test.js +173 -0
- package/dist/test/index.test.js.map +1 -0
- package/index.ts +98 -0
- package/index.ts.backup +49 -0
- package/inputSchema.ts +35 -0
- package/package.json +38 -0
- package/test/index.test.ts +192 -0
- package/tsconfig.json +17 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# @blokjs/if-else
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Initial public release of Blok packages.
|
|
8
|
+
|
|
9
|
+
This release includes:
|
|
10
|
+
|
|
11
|
+
- Core packages: @blokjs/shared, @blokjs/helper, @blokjs/runner
|
|
12
|
+
- Node packages: @blokjs/api-call, @blokjs/if-else, @blokjs/react
|
|
13
|
+
- Trigger packages: pubsub, queue, webhook, websocket, worker, cron, grpc
|
|
14
|
+
- CLI tool: blokctl
|
|
15
|
+
- Editor support: @blokjs/lsp-server, @blokjs/syntax
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
- @blokjs/shared@0.2.0
|
|
21
|
+
- @blokjs/helper@0.2.0
|
|
22
|
+
- @blokjs/runner@0.2.0
|
|
23
|
+
|
|
24
|
+
## 0.0.30
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- Updated dependencies
|
|
29
|
+
- @blokjs/runner@0.1.26
|
|
30
|
+
|
|
31
|
+
## 0.0.29
|
|
32
|
+
|
|
33
|
+
### Patch Changes
|
|
34
|
+
|
|
35
|
+
- Updated dependencies
|
|
36
|
+
- @blokjs/runner@0.1.25
|
|
37
|
+
|
|
38
|
+
## 0.0.28
|
|
39
|
+
|
|
40
|
+
### Patch Changes
|
|
41
|
+
|
|
42
|
+
- Updated dependencies
|
|
43
|
+
- @blokjs/runner@0.1.24
|
|
44
|
+
|
|
45
|
+
## 0.0.27
|
|
46
|
+
|
|
47
|
+
### Patch Changes
|
|
48
|
+
|
|
49
|
+
- Updated dependencies
|
|
50
|
+
- @blokjs/runner@0.1.23
|
|
51
|
+
|
|
52
|
+
## 0.0.26
|
|
53
|
+
|
|
54
|
+
### Patch Changes
|
|
55
|
+
|
|
56
|
+
- Updated dependencies
|
|
57
|
+
- @blokjs/runner@0.1.22
|
|
58
|
+
|
|
59
|
+
## 0.0.25
|
|
60
|
+
|
|
61
|
+
### Patch Changes
|
|
62
|
+
|
|
63
|
+
- Updated dependencies
|
|
64
|
+
- @blokjs/runner@0.1.21
|
|
65
|
+
|
|
66
|
+
## 0.0.24
|
|
67
|
+
|
|
68
|
+
### Patch Changes
|
|
69
|
+
|
|
70
|
+
- Updated dependencies
|
|
71
|
+
- @blokjs/helper@0.1.5
|
|
72
|
+
- @blokjs/runner@0.1.20
|
|
73
|
+
|
|
74
|
+
## 0.0.23
|
|
75
|
+
|
|
76
|
+
### Patch Changes
|
|
77
|
+
|
|
78
|
+
- Updated dependencies
|
|
79
|
+
- @blokjs/runner@0.1.19
|
|
80
|
+
- @blokjs/shared@0.0.9
|
|
81
|
+
|
|
82
|
+
## 0.0.22
|
|
83
|
+
|
|
84
|
+
### Patch Changes
|
|
85
|
+
|
|
86
|
+
- Added examples and create project' command to include examples and 'create node' command with options for type ('module' or 'class') and template ('class' or 'ui')
|
|
87
|
+
- Updated dependencies
|
|
88
|
+
- @blokjs/runner@0.1.18
|
|
89
|
+
- @blokjs/shared@0.0.8
|
|
90
|
+
|
|
91
|
+
## 0.0.21
|
|
92
|
+
|
|
93
|
+
### Patch Changes
|
|
94
|
+
|
|
95
|
+
- Updated dependencies
|
|
96
|
+
- @blokjs/runner@0.1.17
|
|
97
|
+
|
|
98
|
+
## 0.0.20
|
|
99
|
+
|
|
100
|
+
### Patch Changes
|
|
101
|
+
|
|
102
|
+
- Added support for YAML, XML and TOML in the workflow file. Upgraded package version recommended by Dependabot.
|
|
103
|
+
- Updated dependencies
|
|
104
|
+
- @blokjs/helper@0.1.4
|
|
105
|
+
- @blokjs/runner@0.1.16
|
|
106
|
+
- @blokjs/shared@0.0.7
|
|
107
|
+
|
|
108
|
+
## 0.0.19
|
|
109
|
+
|
|
110
|
+
### Patch Changes
|
|
111
|
+
|
|
112
|
+
- Improved the BlokService base class to accept a InputType. This force developer to always create a type to define the Node handle input. Added unit test for pending projects like if-else and api-call.
|
|
113
|
+
- Updated dependencies
|
|
114
|
+
- @blokjs/runner@0.1.15
|
|
115
|
+
|
|
116
|
+
## 0.0.18
|
|
117
|
+
|
|
118
|
+
### Patch Changes
|
|
119
|
+
|
|
120
|
+
- Updated dependencies
|
|
121
|
+
- @blokjs/shared@0.0.6
|
|
122
|
+
- @blokjs/runner@0.1.14
|
|
123
|
+
|
|
124
|
+
## 0.0.17
|
|
125
|
+
|
|
126
|
+
### Patch Changes
|
|
127
|
+
|
|
128
|
+
- Updated dependencies
|
|
129
|
+
- @blokjs/runner@0.1.13
|
|
130
|
+
- @blokjs/shared@0.0.5
|
|
131
|
+
|
|
132
|
+
## 0.0.16
|
|
133
|
+
|
|
134
|
+
### Patch Changes
|
|
135
|
+
|
|
136
|
+
- Updated dependencies
|
|
137
|
+
- @blokjs/runner@0.1.12
|
|
138
|
+
- @blokjs/shared@0.0.4
|
|
139
|
+
|
|
140
|
+
## 0.0.15
|
|
141
|
+
|
|
142
|
+
### Patch Changes
|
|
143
|
+
|
|
144
|
+
- Updated dependencies
|
|
145
|
+
- @blokjs/runner@0.1.11
|
|
146
|
+
|
|
147
|
+
## 0.0.14
|
|
148
|
+
|
|
149
|
+
### Patch Changes
|
|
150
|
+
|
|
151
|
+
- Updated dependencies
|
|
152
|
+
- @blokjs/runner@0.1.10
|
|
153
|
+
|
|
154
|
+
## 0.0.13
|
|
155
|
+
|
|
156
|
+
### Patch Changes
|
|
157
|
+
|
|
158
|
+
- Improved and extended the open telemetry feature
|
|
159
|
+
- Updated dependencies
|
|
160
|
+
- @blokjs/runner@0.1.9
|
|
161
|
+
- @blokjs/shared@0.0.3
|
|
162
|
+
|
|
163
|
+
## 0.0.12
|
|
164
|
+
|
|
165
|
+
### Patch Changes
|
|
166
|
+
|
|
167
|
+
- Fixed open telemetry issues and types
|
|
168
|
+
- Updated dependencies
|
|
169
|
+
- @blokjs/runner@0.1.8
|
|
170
|
+
- @blokjs/shared@0.0.2
|
|
171
|
+
|
|
172
|
+
## 0.0.11
|
|
173
|
+
|
|
174
|
+
### Patch Changes
|
|
175
|
+
|
|
176
|
+
- Fixed issue with the cli node creation test
|
|
177
|
+
- Updated dependencies
|
|
178
|
+
- @blokjs/runner@0.1.7
|
|
179
|
+
- @blokjs/shared@0.0.1
|
|
180
|
+
|
|
181
|
+
## 0.0.10
|
|
182
|
+
|
|
183
|
+
### Patch Changes
|
|
184
|
+
|
|
185
|
+
- Migrated and refactored shared library
|
|
186
|
+
- Updated dependencies
|
|
187
|
+
- @blokjs/runner@0.1.6
|
|
188
|
+
|
|
189
|
+
## 0.0.9
|
|
190
|
+
|
|
191
|
+
### Patch Changes
|
|
192
|
+
|
|
193
|
+
- Updated dependencies [e5225d2]
|
|
194
|
+
- @blokjs/runner@0.1.5
|
|
195
|
+
|
|
196
|
+
## 0.0.8
|
|
197
|
+
|
|
198
|
+
### Patch Changes
|
|
199
|
+
|
|
200
|
+
- Fixed build version
|
|
201
|
+
|
|
202
|
+
## 0.0.7
|
|
203
|
+
|
|
204
|
+
### Patch Changes
|
|
205
|
+
|
|
206
|
+
- Added main property to package.json
|
|
207
|
+
|
|
208
|
+
## 0.0.6
|
|
209
|
+
|
|
210
|
+
### Patch Changes
|
|
211
|
+
|
|
212
|
+
- Publishing those packages to npmjs
|
|
213
|
+
|
|
214
|
+
## 0.0.5
|
|
215
|
+
|
|
216
|
+
### Patch Changes
|
|
217
|
+
|
|
218
|
+
- Updated dependencies
|
|
219
|
+
- @blokjs/helper@0.1.3
|
|
220
|
+
- @blokjs/runner@0.1.4
|
|
221
|
+
|
|
222
|
+
## 0.0.4
|
|
223
|
+
|
|
224
|
+
### Patch Changes
|
|
225
|
+
|
|
226
|
+
- Updated dependencies
|
|
227
|
+
- @blokjs/helper@0.1.2
|
|
228
|
+
- @blokjs/runner@0.1.3
|
|
229
|
+
|
|
230
|
+
## 0.0.3
|
|
231
|
+
|
|
232
|
+
### Patch Changes
|
|
233
|
+
|
|
234
|
+
- Updated dependencies
|
|
235
|
+
- @blokjs/helper@0.1.1
|
|
236
|
+
- @blokjs/runner@0.1.2
|
|
237
|
+
|
|
238
|
+
## 0.0.2
|
|
239
|
+
|
|
240
|
+
### Patch Changes
|
|
241
|
+
|
|
242
|
+
- Updated dependencies
|
|
243
|
+
- @blokjs/runner@0.1.1
|
|
244
|
+
|
|
245
|
+
## 0.0.1
|
|
246
|
+
|
|
247
|
+
### Patch Changes
|
|
248
|
+
|
|
249
|
+
- Updated dependencies
|
|
250
|
+
- @blokjs/helper@0.1.0
|
|
251
|
+
- @blokjs/runner@0.1.0
|
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Configuration Options
|
|
2
|
+
The IfElse node allows you to have a conditional statement and call other nodes depending on the conditions
|
|
3
|
+
|
|
4
|
+
## Node properties
|
|
5
|
+
|
|
6
|
+
### Required properties
|
|
7
|
+
- `conditions` (array): List of conditions to check
|
|
8
|
+
- `type` (string if | else): type of the condition
|
|
9
|
+
- `condition` (string): The condition string to be checked
|
|
10
|
+
- `steps` (array): List of steps to execute if the condition is true
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## Usage/Examples
|
|
14
|
+
### Step Configuration
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"name": "if-else",
|
|
19
|
+
"node": "if-else@1.0.0",
|
|
20
|
+
"type": "local"
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Node Configuration
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
"if-else": {
|
|
29
|
+
"conditions": [
|
|
30
|
+
{
|
|
31
|
+
"type": "if",
|
|
32
|
+
"condition": "data !== undefined",
|
|
33
|
+
"steps": []
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"type": "else",
|
|
37
|
+
"steps": []
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
package/config.json
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "if-else",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Conditional statement to check if a property is equal to a value",
|
|
5
|
+
"group": "FLOW_CONTROL",
|
|
6
|
+
"config": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"conditions": {
|
|
10
|
+
"type": "array",
|
|
11
|
+
"description": "List of conditions to check",
|
|
12
|
+
"items": [
|
|
13
|
+
{
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"type": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"default": "if",
|
|
19
|
+
"description": "Type of the condition"
|
|
20
|
+
},
|
|
21
|
+
"condition": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "Condition to check",
|
|
24
|
+
"default": "data !== undefined"
|
|
25
|
+
},
|
|
26
|
+
"steps": {
|
|
27
|
+
"type": "array",
|
|
28
|
+
"items": {
|
|
29
|
+
"type": "object",
|
|
30
|
+
"properties": {
|
|
31
|
+
"name": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "Name of the step"
|
|
34
|
+
},
|
|
35
|
+
"node": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"description": "Node of the step"
|
|
38
|
+
},
|
|
39
|
+
"type": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "Type of the step",
|
|
42
|
+
"default": "local"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"required": ["name", "node", "type"]
|
|
46
|
+
},
|
|
47
|
+
"description": "List of steps to execute if the condition is true"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"required": ["type", "condition", "steps"]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"type": "object",
|
|
54
|
+
"properties": {
|
|
55
|
+
"type": {
|
|
56
|
+
"type": "string"
|
|
57
|
+
},
|
|
58
|
+
"steps": {
|
|
59
|
+
"type": "array",
|
|
60
|
+
"items": {
|
|
61
|
+
"type": "object",
|
|
62
|
+
"properties": {
|
|
63
|
+
"name": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"description": "Name of the step"
|
|
66
|
+
},
|
|
67
|
+
"node": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"description": "Node of the step"
|
|
70
|
+
},
|
|
71
|
+
"type": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"description": "Type of the step",
|
|
74
|
+
"default": "local"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"required": ["name", "node", "type"]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"required": ["type", "steps"]
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"required": ["conditions"],
|
|
87
|
+
"example": {
|
|
88
|
+
"conditions": [
|
|
89
|
+
{
|
|
90
|
+
"type": "if",
|
|
91
|
+
"condition": "data !== undefined",
|
|
92
|
+
"steps": []
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"type": "else",
|
|
96
|
+
"steps": []
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"inputs": {
|
|
102
|
+
"type": "any",
|
|
103
|
+
"description": "This node accept an anything as input"
|
|
104
|
+
},
|
|
105
|
+
"output": {
|
|
106
|
+
"type": "any",
|
|
107
|
+
"description": "This node return the result of the steps"
|
|
108
|
+
},
|
|
109
|
+
"steps": {
|
|
110
|
+
"type": "boolean"
|
|
111
|
+
},
|
|
112
|
+
"functions": {
|
|
113
|
+
"type": "array",
|
|
114
|
+
"items": {}
|
|
115
|
+
}
|
|
116
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If-Else Node - Function-First Implementation
|
|
3
|
+
*
|
|
4
|
+
* Control flow node that evaluates conditions and returns the matching branch's steps.
|
|
5
|
+
* Migrated from class-based to function-first pattern using defineNode.
|
|
6
|
+
*/
|
|
7
|
+
import { type Condition } from "@blokjs/runner";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
declare const _default: import("@blokjs/runner").FunctionNode<z.ZodArray<z.ZodObject<{
|
|
10
|
+
type: z.ZodEnum<["if", "else"]>;
|
|
11
|
+
condition: z.ZodOptional<z.ZodString>;
|
|
12
|
+
steps: z.ZodArray<z.ZodAny, "many">;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
type: "if" | "else";
|
|
15
|
+
steps: any[];
|
|
16
|
+
condition?: string | undefined;
|
|
17
|
+
}, {
|
|
18
|
+
type: "if" | "else";
|
|
19
|
+
steps: any[];
|
|
20
|
+
condition?: string | undefined;
|
|
21
|
+
}>, "many">, z.ZodArray<z.ZodAny, "many">>;
|
|
22
|
+
export default _default;
|
|
23
|
+
export type NodeOptions = {
|
|
24
|
+
conditions: Condition[];
|
|
25
|
+
};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If-Else Node - Function-First Implementation
|
|
3
|
+
*
|
|
4
|
+
* Control flow node that evaluates conditions and returns the matching branch's steps.
|
|
5
|
+
* Migrated from class-based to function-first pattern using defineNode.
|
|
6
|
+
*/
|
|
7
|
+
import { defineNode } from "@blokjs/runner";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
/**
|
|
10
|
+
* Helper function to evaluate JavaScript expressions in context
|
|
11
|
+
* Replicates NodeBase.runJs() functionality
|
|
12
|
+
*/
|
|
13
|
+
function runJs(str, ctx, data = {}, func = {}, vars = {}) {
|
|
14
|
+
return Function("ctx", "data", "func", "vars", `"use strict";return (${str});`)(ctx, data, func, vars);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Zod schema for a single condition
|
|
18
|
+
*/
|
|
19
|
+
const conditionSchema = z.object({
|
|
20
|
+
type: z.enum(["if", "else"]),
|
|
21
|
+
condition: z.string().optional(),
|
|
22
|
+
steps: z.array(z.any()), // NodeBase[] - can't properly type this with Zod
|
|
23
|
+
});
|
|
24
|
+
export default defineNode({
|
|
25
|
+
name: "if-else",
|
|
26
|
+
description: "Evaluates conditions and returns the matching branch's steps for execution",
|
|
27
|
+
// This is a flow control node — the runner uses processFlow() instead of process()
|
|
28
|
+
flow: true,
|
|
29
|
+
// Input: Array of conditions (if, else if, else)
|
|
30
|
+
input: z.array(conditionSchema),
|
|
31
|
+
// Output: Array of NodeBase (steps to execute)
|
|
32
|
+
// Note: This is a special flow control node that returns steps, not a standard response
|
|
33
|
+
output: z.array(z.any()),
|
|
34
|
+
async execute(ctx, inputs) {
|
|
35
|
+
const conditions = inputs;
|
|
36
|
+
let steps = [];
|
|
37
|
+
// Validate first condition is "if"
|
|
38
|
+
const firstCondition = conditions[0];
|
|
39
|
+
if (firstCondition.type !== "if") {
|
|
40
|
+
throw new Error("First condition must be an if");
|
|
41
|
+
}
|
|
42
|
+
// Validate last condition is "else" (if there are multiple conditions)
|
|
43
|
+
if (conditions.length > 1) {
|
|
44
|
+
const lastCondition = conditions[conditions.length - 1];
|
|
45
|
+
if (lastCondition.type !== "else") {
|
|
46
|
+
throw new Error("Last condition must be an else");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Evaluate conditions in order
|
|
50
|
+
for (let i = 0; i < conditions.length; i++) {
|
|
51
|
+
const condition = conditions[i];
|
|
52
|
+
// If condition has a JavaScript expression, evaluate it
|
|
53
|
+
if (condition.condition !== undefined && condition.condition.trim() !== "") {
|
|
54
|
+
const result = runJs(condition.condition, ctx, ctx.response.data, {}, ctx.vars || {});
|
|
55
|
+
// If condition matches, use these steps and break
|
|
56
|
+
if (result) {
|
|
57
|
+
steps = condition.steps;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// No condition (else block) - use these steps and break
|
|
63
|
+
steps = condition.steps;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Return steps as NodeBase[] (flow control)
|
|
68
|
+
// The runner will recognize this as a flow node and execute the steps
|
|
69
|
+
return steps;
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export declare const inputSchema: {
|
|
2
|
+
$schema: string;
|
|
3
|
+
title: string;
|
|
4
|
+
type: string;
|
|
5
|
+
items: {
|
|
6
|
+
type: string;
|
|
7
|
+
properties: {
|
|
8
|
+
type: {
|
|
9
|
+
type: string;
|
|
10
|
+
};
|
|
11
|
+
steps: {
|
|
12
|
+
type: string;
|
|
13
|
+
items: {
|
|
14
|
+
type: string;
|
|
15
|
+
properties: {
|
|
16
|
+
name: {
|
|
17
|
+
type: string;
|
|
18
|
+
};
|
|
19
|
+
node: {
|
|
20
|
+
type: string;
|
|
21
|
+
};
|
|
22
|
+
type: {
|
|
23
|
+
type: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
required: string[];
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
condition: {
|
|
30
|
+
type: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
required: string[];
|
|
34
|
+
};
|
|
35
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const inputSchema = {
|
|
2
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
title: "Generated schema for Root",
|
|
4
|
+
type: "array",
|
|
5
|
+
items: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
type: {
|
|
9
|
+
type: "string",
|
|
10
|
+
},
|
|
11
|
+
steps: {
|
|
12
|
+
type: "array",
|
|
13
|
+
items: {
|
|
14
|
+
type: "object",
|
|
15
|
+
properties: {
|
|
16
|
+
name: {
|
|
17
|
+
type: "string",
|
|
18
|
+
},
|
|
19
|
+
node: {
|
|
20
|
+
type: "string",
|
|
21
|
+
},
|
|
22
|
+
type: {
|
|
23
|
+
type: "string",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
required: ["name", "node", "type"],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
condition: {
|
|
30
|
+
type: "string",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
required: ["type", "steps"],
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=inputSchema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inputSchema.js","sourceRoot":"","sources":["../inputSchema.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;IAC1B,OAAO,EAAE,yCAAyC;IAClD,KAAK,EAAE,2BAA2B;IAClC,IAAI,EAAE,OAAO;IACb,KAAK,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACX,IAAI,EAAE;gBACL,IAAI,EAAE,QAAQ;aACd;YACD,KAAK,EAAE;gBACN,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACX,IAAI,EAAE;4BACL,IAAI,EAAE,QAAQ;yBACd;wBACD,IAAI,EAAE;4BACL,IAAI,EAAE,QAAQ;yBACd;wBACD,IAAI,EAAE;4BACL,IAAI,EAAE,QAAQ;yBACd;qBACD;oBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;iBAClC;aACD;YACD,SAAS,EAAE;gBACV,IAAI,EAAE,QAAQ;aACd;SACD;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;KAC3B;CACD,CAAC"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If-Else Node Tests - Updated for Function-First Implementation
|
|
3
|
+
*
|
|
4
|
+
* Tests migrated from class-based to function-first pattern.
|
|
5
|
+
* All existing behavior is preserved.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, expect, it, vi } from "vitest";
|
|
8
|
+
import IfElseNode from "../index";
|
|
9
|
+
describe("IfElse Node - Function-First", () => {
|
|
10
|
+
const mockContext = {
|
|
11
|
+
response: {
|
|
12
|
+
data: null,
|
|
13
|
+
error: null,
|
|
14
|
+
success: true,
|
|
15
|
+
},
|
|
16
|
+
request: {
|
|
17
|
+
body: {},
|
|
18
|
+
headers: {},
|
|
19
|
+
params: {},
|
|
20
|
+
query: {},
|
|
21
|
+
method: "GET",
|
|
22
|
+
},
|
|
23
|
+
config: {
|
|
24
|
+
"if-else": {},
|
|
25
|
+
},
|
|
26
|
+
id: "test-id",
|
|
27
|
+
workflow_name: "test-workflow",
|
|
28
|
+
workflow_path: "/test",
|
|
29
|
+
error: {
|
|
30
|
+
message: [],
|
|
31
|
+
},
|
|
32
|
+
logger: {
|
|
33
|
+
log: vi.fn(),
|
|
34
|
+
info: vi.fn(),
|
|
35
|
+
error: vi.fn(),
|
|
36
|
+
warn: vi.fn(),
|
|
37
|
+
debug: vi.fn(),
|
|
38
|
+
},
|
|
39
|
+
vars: {},
|
|
40
|
+
env: {},
|
|
41
|
+
eventLogger: null,
|
|
42
|
+
_PRIVATE_: null,
|
|
43
|
+
};
|
|
44
|
+
const step = {
|
|
45
|
+
name: "node1",
|
|
46
|
+
run: async (ctx, data) => ({}),
|
|
47
|
+
};
|
|
48
|
+
it("should execute the correct steps when if condition is true", async () => {
|
|
49
|
+
const conditions = [
|
|
50
|
+
{
|
|
51
|
+
type: "if",
|
|
52
|
+
condition: "ctx.request.method === 'GET'",
|
|
53
|
+
steps: [
|
|
54
|
+
(() => {
|
|
55
|
+
step.name = "step1";
|
|
56
|
+
return step;
|
|
57
|
+
})(),
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
type: "else",
|
|
62
|
+
steps: [step],
|
|
63
|
+
condition: "",
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
mockContext.request.method = "GET";
|
|
67
|
+
const result = (await IfElseNode.handle(mockContext, conditions));
|
|
68
|
+
const steps = result.data;
|
|
69
|
+
expect(steps[0].name).toEqual("step1");
|
|
70
|
+
});
|
|
71
|
+
it("should execute the else step when if condition is false", async () => {
|
|
72
|
+
const conditions = [
|
|
73
|
+
{
|
|
74
|
+
type: "if",
|
|
75
|
+
condition: "ctx.request.method === 'POST'",
|
|
76
|
+
steps: [step],
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
type: "else",
|
|
80
|
+
steps: [
|
|
81
|
+
(() => {
|
|
82
|
+
step.name = "step2";
|
|
83
|
+
return step;
|
|
84
|
+
})(),
|
|
85
|
+
],
|
|
86
|
+
condition: "",
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
const result = (await IfElseNode.handle(mockContext, conditions));
|
|
90
|
+
const steps = result.data;
|
|
91
|
+
expect(steps[0].name).toEqual("step2");
|
|
92
|
+
});
|
|
93
|
+
it("should throw an error if the first condition is not 'if'", async () => {
|
|
94
|
+
const conditions = [
|
|
95
|
+
{
|
|
96
|
+
type: "else",
|
|
97
|
+
steps: [step],
|
|
98
|
+
condition: "",
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
const result = (await IfElseNode.handle(mockContext, conditions));
|
|
102
|
+
expect(result.success).toBe(false);
|
|
103
|
+
expect(result.error).toBeDefined();
|
|
104
|
+
});
|
|
105
|
+
it("should throw an error if the last condition is not 'else'", async () => {
|
|
106
|
+
const conditions = [
|
|
107
|
+
{
|
|
108
|
+
type: "if",
|
|
109
|
+
condition: "ctx.request.method === 'GET'",
|
|
110
|
+
steps: [step],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: "if",
|
|
114
|
+
condition: "ctx.request.method === 'POST'",
|
|
115
|
+
steps: [step],
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
const result = (await IfElseNode.handle(mockContext, conditions));
|
|
119
|
+
expect(result.success).toBe(false);
|
|
120
|
+
expect(result.error).toBeDefined();
|
|
121
|
+
});
|
|
122
|
+
it("should execute the first matching condition", async () => {
|
|
123
|
+
const conditions = [
|
|
124
|
+
{
|
|
125
|
+
type: "if",
|
|
126
|
+
condition: "ctx.request.method === 'POST'",
|
|
127
|
+
steps: [step],
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
type: "if",
|
|
131
|
+
condition: "ctx.request.method === 'GET'",
|
|
132
|
+
steps: [
|
|
133
|
+
(() => {
|
|
134
|
+
step.name = "step2";
|
|
135
|
+
return step;
|
|
136
|
+
})(),
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
type: "else",
|
|
141
|
+
steps: [step],
|
|
142
|
+
condition: "",
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
mockContext.request.method = "GET";
|
|
146
|
+
const result = (await IfElseNode.handle(mockContext, conditions));
|
|
147
|
+
const steps = result.data;
|
|
148
|
+
expect(steps[0].name).toEqual("step2");
|
|
149
|
+
});
|
|
150
|
+
it("should execute the else condition if none match", async () => {
|
|
151
|
+
const conditions = [
|
|
152
|
+
{
|
|
153
|
+
type: "if",
|
|
154
|
+
condition: "ctx.request.method === 'POST'",
|
|
155
|
+
steps: [step],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
type: "else",
|
|
159
|
+
steps: [
|
|
160
|
+
(() => {
|
|
161
|
+
step.name = "step2";
|
|
162
|
+
return step;
|
|
163
|
+
})(),
|
|
164
|
+
],
|
|
165
|
+
condition: "",
|
|
166
|
+
},
|
|
167
|
+
];
|
|
168
|
+
const result = (await IfElseNode.handle(mockContext, conditions));
|
|
169
|
+
const steps = result.data;
|
|
170
|
+
expect(steps[0].name).toEqual("step2");
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../test/index.test.ts"],"names":[],"mappings":"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"}
|
package/index.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If-Else Node - Function-First Implementation
|
|
3
|
+
*
|
|
4
|
+
* Control flow node that evaluates conditions and returns the matching branch's steps.
|
|
5
|
+
* Migrated from class-based to function-first pattern using defineNode.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ConditionOpts } from "@blokjs/helper";
|
|
9
|
+
import { type Condition, type BlokService, defineNode } from "@blokjs/runner";
|
|
10
|
+
import type { Context, NodeBase } from "@blokjs/shared";
|
|
11
|
+
import type ParamsDictionary from "@blokjs/shared/dist/types/ParamsDictionary";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Helper function to evaluate JavaScript expressions in context
|
|
16
|
+
* Replicates NodeBase.runJs() functionality
|
|
17
|
+
*/
|
|
18
|
+
function runJs(
|
|
19
|
+
str: string,
|
|
20
|
+
ctx: Context,
|
|
21
|
+
data: ParamsDictionary = {},
|
|
22
|
+
func: Record<string, unknown> = {},
|
|
23
|
+
vars: Record<string, unknown> = {},
|
|
24
|
+
): unknown {
|
|
25
|
+
return Function("ctx", "data", "func", "vars", `"use strict";return (${str});`)(ctx, data, func, vars);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Zod schema for a single condition
|
|
30
|
+
*/
|
|
31
|
+
const conditionSchema = z.object({
|
|
32
|
+
type: z.enum(["if", "else"]),
|
|
33
|
+
condition: z.string().optional(),
|
|
34
|
+
steps: z.array(z.any()), // NodeBase[] - can't properly type this with Zod
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export default defineNode({
|
|
38
|
+
name: "if-else",
|
|
39
|
+
description: "Evaluates conditions and returns the matching branch's steps for execution",
|
|
40
|
+
|
|
41
|
+
// This is a flow control node — the runner uses processFlow() instead of process()
|
|
42
|
+
flow: true,
|
|
43
|
+
|
|
44
|
+
// Input: Array of conditions (if, else if, else)
|
|
45
|
+
input: z.array(conditionSchema),
|
|
46
|
+
|
|
47
|
+
// Output: Array of NodeBase (steps to execute)
|
|
48
|
+
// Note: This is a special flow control node that returns steps, not a standard response
|
|
49
|
+
output: z.array(z.any()),
|
|
50
|
+
|
|
51
|
+
async execute(ctx, inputs) {
|
|
52
|
+
const conditions = inputs;
|
|
53
|
+
let steps: NodeBase[] = [];
|
|
54
|
+
|
|
55
|
+
// Validate first condition is "if"
|
|
56
|
+
const firstCondition = conditions[0] as ConditionOpts;
|
|
57
|
+
if (firstCondition.type !== "if") {
|
|
58
|
+
throw new Error("First condition must be an if");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Validate last condition is "else" (if there are multiple conditions)
|
|
62
|
+
if (conditions.length > 1) {
|
|
63
|
+
const lastCondition = conditions[conditions.length - 1];
|
|
64
|
+
if (lastCondition.type !== "else") {
|
|
65
|
+
throw new Error("Last condition must be an else");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Evaluate conditions in order
|
|
70
|
+
for (let i = 0; i < conditions.length; i++) {
|
|
71
|
+
const condition = conditions[i];
|
|
72
|
+
|
|
73
|
+
// If condition has a JavaScript expression, evaluate it
|
|
74
|
+
if (condition.condition !== undefined && condition.condition.trim() !== "") {
|
|
75
|
+
const result = runJs(condition.condition, ctx, ctx.response.data as ParamsDictionary, {}, ctx.vars || {});
|
|
76
|
+
|
|
77
|
+
// If condition matches, use these steps and break
|
|
78
|
+
if (result) {
|
|
79
|
+
steps = condition.steps as NodeBase[];
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
// No condition (else block) - use these steps and break
|
|
84
|
+
steps = condition.steps as NodeBase[];
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Return steps as NodeBase[] (flow control)
|
|
90
|
+
// The runner will recognize this as a flow node and execute the steps
|
|
91
|
+
return steps as unknown as BlokService<Condition[]>[];
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// For backward compatibility
|
|
96
|
+
export type NodeOptions = {
|
|
97
|
+
conditions: Condition[];
|
|
98
|
+
};
|
package/index.ts.backup
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { ConditionOpts } from "@blok/helper";
|
|
2
|
+
import { type Condition, type INanoServiceResponse, NanoService } from "@blok/runner";
|
|
3
|
+
import type { Context, NodeBase } from "@blok/shared";
|
|
4
|
+
import type ParamsDictionary from "@blok/shared/dist/types/ParamsDictionary";
|
|
5
|
+
|
|
6
|
+
export default class IfElse extends NanoService<Array<Condition>> {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
this.flow = true;
|
|
10
|
+
this.contentType = "";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async handle(ctx: Context, inputs: Array<Condition>): Promise<INanoServiceResponse | NanoService<Condition[]>[]> {
|
|
14
|
+
let steps: NodeBase[] = [];
|
|
15
|
+
const conditions = inputs;
|
|
16
|
+
|
|
17
|
+
const firstCondition = conditions[0] as ConditionOpts;
|
|
18
|
+
if (firstCondition.type !== "if") throw new Error("First condition must be an if");
|
|
19
|
+
|
|
20
|
+
if (conditions.length > 1) {
|
|
21
|
+
const lastCondition = conditions[conditions.length - 1];
|
|
22
|
+
if (lastCondition.type !== "else") throw new Error("Last condition must be an else");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
for (let i = 0; i < conditions.length; i++) {
|
|
26
|
+
const condition = conditions[i];
|
|
27
|
+
|
|
28
|
+
if (condition.condition !== undefined && condition.condition.trim() !== "") {
|
|
29
|
+
const result = this.runJs(condition.condition, ctx, ctx.response.data as ParamsDictionary, {}, ctx.vars);
|
|
30
|
+
|
|
31
|
+
if (result) {
|
|
32
|
+
steps = condition.steps as NodeBase[];
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
steps = condition.steps as NodeBase[];
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return steps as unknown as NanoService<Condition[]>[];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type NodeOptions = {
|
|
46
|
+
conditions: Condition[];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type { NodeOptions };
|
package/inputSchema.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const inputSchema = {
|
|
2
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
title: "Generated schema for Root",
|
|
4
|
+
type: "array",
|
|
5
|
+
items: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
type: {
|
|
9
|
+
type: "string",
|
|
10
|
+
},
|
|
11
|
+
steps: {
|
|
12
|
+
type: "array",
|
|
13
|
+
items: {
|
|
14
|
+
type: "object",
|
|
15
|
+
properties: {
|
|
16
|
+
name: {
|
|
17
|
+
type: "string",
|
|
18
|
+
},
|
|
19
|
+
node: {
|
|
20
|
+
type: "string",
|
|
21
|
+
},
|
|
22
|
+
type: {
|
|
23
|
+
type: "string",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
required: ["name", "node", "type"],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
condition: {
|
|
30
|
+
type: "string",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
required: ["type", "steps"],
|
|
34
|
+
},
|
|
35
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@blokjs/if-else",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "blok if-else",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=18.0.0"
|
|
8
|
+
},
|
|
9
|
+
"author": "Deskree Technologies Inc.",
|
|
10
|
+
"license": "Apache-2.0",
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"scripts": {
|
|
14
|
+
"start:dev": "bun --watch run src/index.ts",
|
|
15
|
+
"build": "rimraf ./dist && tsc",
|
|
16
|
+
"build:dev": "tsc --watch",
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"test:dev": "vitest --watch"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/lodash": "^4.14.196",
|
|
22
|
+
"@types/node": "^22.15.21",
|
|
23
|
+
"rimraf": "^6.1.2",
|
|
24
|
+
"typescript": "^5.8.3",
|
|
25
|
+
"vitest": "^4.0.18"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@blokjs/helper": "workspace:*",
|
|
29
|
+
"@blokjs/runner": "workspace:*",
|
|
30
|
+
"@blokjs/shared": "workspace:*",
|
|
31
|
+
"lodash": "^4.17.21",
|
|
32
|
+
"zod": "^3.24.2"
|
|
33
|
+
},
|
|
34
|
+
"private": false,
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If-Else Node Tests - Updated for Function-First Implementation
|
|
3
|
+
*
|
|
4
|
+
* Tests migrated from class-based to function-first pattern.
|
|
5
|
+
* All existing behavior is preserved.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Condition, IBlokResponse, JsonLikeObject, ParamsDictionary } from "@blokjs/runner";
|
|
9
|
+
import type { Context, NodeBase, ResponseContext } from "@blokjs/shared";
|
|
10
|
+
import { describe, expect, it, vi } from "vitest";
|
|
11
|
+
import IfElseNode from "../index";
|
|
12
|
+
|
|
13
|
+
describe("IfElse Node - Function-First", () => {
|
|
14
|
+
const mockContext: Context = {
|
|
15
|
+
response: {
|
|
16
|
+
data: null,
|
|
17
|
+
error: null,
|
|
18
|
+
success: true,
|
|
19
|
+
},
|
|
20
|
+
request: {
|
|
21
|
+
body: {} as ParamsDictionary,
|
|
22
|
+
headers: {},
|
|
23
|
+
params: {},
|
|
24
|
+
query: {},
|
|
25
|
+
method: "GET",
|
|
26
|
+
},
|
|
27
|
+
config: {
|
|
28
|
+
"if-else": {},
|
|
29
|
+
},
|
|
30
|
+
id: "test-id",
|
|
31
|
+
workflow_name: "test-workflow",
|
|
32
|
+
workflow_path: "/test",
|
|
33
|
+
error: {
|
|
34
|
+
message: [],
|
|
35
|
+
},
|
|
36
|
+
logger: {
|
|
37
|
+
log: vi.fn(),
|
|
38
|
+
info: vi.fn(),
|
|
39
|
+
error: vi.fn(),
|
|
40
|
+
warn: vi.fn(),
|
|
41
|
+
debug: vi.fn(),
|
|
42
|
+
} as unknown as Context["logger"],
|
|
43
|
+
vars: {},
|
|
44
|
+
env: {},
|
|
45
|
+
eventLogger: null,
|
|
46
|
+
_PRIVATE_: null,
|
|
47
|
+
} as unknown as Context;
|
|
48
|
+
|
|
49
|
+
const step: {
|
|
50
|
+
name: string;
|
|
51
|
+
run?: (ctx: Context, data: ParamsDictionary) => Promise<ResponseContext>;
|
|
52
|
+
} = {
|
|
53
|
+
name: "node1",
|
|
54
|
+
run: async (ctx: Context, data: ParamsDictionary): Promise<ResponseContext> => ({}) as ResponseContext,
|
|
55
|
+
} as unknown as NodeBase;
|
|
56
|
+
|
|
57
|
+
it("should execute the correct steps when if condition is true", async () => {
|
|
58
|
+
const conditions: Condition[] = [
|
|
59
|
+
{
|
|
60
|
+
type: "if",
|
|
61
|
+
condition: "ctx.request.method === 'GET'",
|
|
62
|
+
steps: [
|
|
63
|
+
(() => {
|
|
64
|
+
step.name = "step1";
|
|
65
|
+
return step as unknown as NodeBase;
|
|
66
|
+
})(),
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
type: "else",
|
|
71
|
+
steps: [step as unknown as NodeBase],
|
|
72
|
+
condition: "",
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
(mockContext.request as JsonLikeObject).method = "GET";
|
|
77
|
+
const result = (await IfElseNode.handle(mockContext, conditions)) as IBlokResponse;
|
|
78
|
+
const steps = result.data as NodeBase[];
|
|
79
|
+
expect(steps[0].name).toEqual("step1");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should execute the else step when if condition is false", async () => {
|
|
83
|
+
const conditions: Condition[] = [
|
|
84
|
+
{
|
|
85
|
+
type: "if",
|
|
86
|
+
condition: "ctx.request.method === 'POST'",
|
|
87
|
+
steps: [step as unknown as NodeBase],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
type: "else",
|
|
91
|
+
steps: [
|
|
92
|
+
(() => {
|
|
93
|
+
step.name = "step2";
|
|
94
|
+
return step as unknown as NodeBase;
|
|
95
|
+
})(),
|
|
96
|
+
],
|
|
97
|
+
condition: "",
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
const result = (await IfElseNode.handle(mockContext, conditions)) as IBlokResponse;
|
|
102
|
+
const steps = result.data as NodeBase[];
|
|
103
|
+
expect(steps[0].name).toEqual("step2");
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("should throw an error if the first condition is not 'if'", async () => {
|
|
107
|
+
const conditions: Condition[] = [
|
|
108
|
+
{
|
|
109
|
+
type: "else",
|
|
110
|
+
steps: [step as unknown as NodeBase],
|
|
111
|
+
condition: "",
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
const result = (await IfElseNode.handle(mockContext, conditions)) as IBlokResponse;
|
|
116
|
+
expect(result.success).toBe(false);
|
|
117
|
+
expect(result.error).toBeDefined();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("should throw an error if the last condition is not 'else'", async () => {
|
|
121
|
+
const conditions: Condition[] = [
|
|
122
|
+
{
|
|
123
|
+
type: "if",
|
|
124
|
+
condition: "ctx.request.method === 'GET'",
|
|
125
|
+
steps: [step as unknown as NodeBase],
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
type: "if",
|
|
129
|
+
condition: "ctx.request.method === 'POST'",
|
|
130
|
+
steps: [step as unknown as NodeBase],
|
|
131
|
+
},
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
const result = (await IfElseNode.handle(mockContext, conditions)) as IBlokResponse;
|
|
135
|
+
expect(result.success).toBe(false);
|
|
136
|
+
expect(result.error).toBeDefined();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("should execute the first matching condition", async () => {
|
|
140
|
+
const conditions: Condition[] = [
|
|
141
|
+
{
|
|
142
|
+
type: "if",
|
|
143
|
+
condition: "ctx.request.method === 'POST'",
|
|
144
|
+
steps: [step as unknown as NodeBase],
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: "if",
|
|
148
|
+
condition: "ctx.request.method === 'GET'",
|
|
149
|
+
steps: [
|
|
150
|
+
(() => {
|
|
151
|
+
step.name = "step2";
|
|
152
|
+
return step as unknown as NodeBase;
|
|
153
|
+
})(),
|
|
154
|
+
],
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
type: "else",
|
|
158
|
+
steps: [step as unknown as NodeBase],
|
|
159
|
+
condition: "",
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
(mockContext.request as JsonLikeObject).method = "GET";
|
|
164
|
+
const result = (await IfElseNode.handle(mockContext, conditions)) as IBlokResponse;
|
|
165
|
+
const steps = result.data as NodeBase[];
|
|
166
|
+
expect(steps[0].name).toEqual("step2");
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("should execute the else condition if none match", async () => {
|
|
170
|
+
const conditions: Condition[] = [
|
|
171
|
+
{
|
|
172
|
+
type: "if",
|
|
173
|
+
condition: "ctx.request.method === 'POST'",
|
|
174
|
+
steps: [step as unknown as NodeBase],
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
type: "else",
|
|
178
|
+
steps: [
|
|
179
|
+
(() => {
|
|
180
|
+
step.name = "step2";
|
|
181
|
+
return step as unknown as NodeBase;
|
|
182
|
+
})(),
|
|
183
|
+
],
|
|
184
|
+
condition: "",
|
|
185
|
+
},
|
|
186
|
+
];
|
|
187
|
+
|
|
188
|
+
const result = (await IfElseNode.handle(mockContext, conditions)) as IBlokResponse;
|
|
189
|
+
const steps = result.data as NodeBase[];
|
|
190
|
+
expect(steps[0].name).toEqual("step2");
|
|
191
|
+
});
|
|
192
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2022",
|
|
4
|
+
"module": "es2022",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"sourceMap": true,
|
|
8
|
+
"outDir": "./dist",
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"noUnusedLocals": true,
|
|
13
|
+
"noImplicitReturns": true,
|
|
14
|
+
"skipLibCheck": true
|
|
15
|
+
},
|
|
16
|
+
"compileOnSave": true
|
|
17
|
+
}
|