Skip to content

Commit 6a20ef5

Browse files
committed
move start, terminate and dispose outside diagram operations. This avoids the case of multiple starts and terminate at the schema level
Signed-off-by: Teo Koon Peng <[email protected]>
1 parent 08631b4 commit 6a20ef5

File tree

10 files changed

+417
-704
lines changed

10 files changed

+417
-704
lines changed

diagram.schema.json

Lines changed: 67 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,48 @@
33
"title": "Diagram",
44
"type": "object",
55
"required": [
6-
"ops"
6+
"ops",
7+
"start"
78
],
89
"properties": {
910
"ops": {
1011
"type": "object",
1112
"additionalProperties": {
1213
"$ref": "#/definitions/DiagramOperation"
1314
}
15+
},
16+
"start": {
17+
"description": "Signifies the start of a workflow.",
18+
"allOf": [
19+
{
20+
"$ref": "#/definitions/NextOperation"
21+
}
22+
]
1423
}
1524
},
1625
"definitions": {
17-
"DiagramOperation": {
26+
"BuiltinTarget": {
1827
"oneOf": [
1928
{
20-
"description": "Signifies the start of a workflow. There must be exactly 1 start operation in a diagram.",
21-
"type": "object",
22-
"required": [
23-
"next",
24-
"type"
25-
],
26-
"properties": {
27-
"next": {
28-
"type": "string"
29-
},
30-
"type": {
31-
"type": "string",
32-
"enum": [
33-
"start"
34-
]
35-
}
36-
}
29+
"description": "Use the output to terminate the workflow. This will be the return value of the workflow.",
30+
"type": "string",
31+
"enum": [
32+
"terminate"
33+
]
3734
},
3835
{
39-
"description": "Signifies the end of a workflow. There must be exactly 1 terminate operation in a diagram.",
40-
"type": "object",
41-
"required": [
42-
"type"
43-
],
44-
"properties": {
45-
"type": {
46-
"type": "string",
47-
"enum": [
48-
"terminate"
49-
]
50-
}
51-
}
52-
},
36+
"description": "Dispose of the output.",
37+
"type": "string",
38+
"enum": [
39+
"dispose"
40+
]
41+
}
42+
]
43+
},
44+
"DiagramOperation": {
45+
"oneOf": [
5346
{
54-
"description": "Connect the request to a registered node.\n\n``` # bevy_impulse::Diagram::from_json_str(r#\" { \"ops\": { \"start\": { \"type\": \"start\", \"next\": \"nodeOp\" }, \"nodeOp\": { \"type\": \"node\", \"builder\": \"myNode\", \"next\": \"terminate\" }, \"terminate\": { \"type\": \"terminate\" } } } # \"#)?; # Ok::<_, serde_json::Error>(())",
47+
"description": "Connect the request to a registered node.\n\n``` # bevy_impulse::Diagram::from_json_str(r#\" { \"start\": \"node_op\", \"ops\": { \"node_op\": { \"type\": \"node\", \"builder\": \"my_node_builder\", \"next\": { \"builtin\": \"terminate\" } } } } # \"#)?; # Ok::<_, serde_json::Error>(())",
5548
"type": "object",
5649
"required": [
5750
"builder",
@@ -66,7 +59,7 @@
6659
"default": null
6760
},
6861
"next": {
69-
"type": "string"
62+
"$ref": "#/definitions/NextOperation"
7063
},
7164
"type": {
7265
"type": "string",
@@ -77,7 +70,7 @@
7770
}
7871
},
7972
{
80-
"description": "If the request is cloneable, clone it into multiple responses.\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"ops\": { \"start\": { \"type\": \"start\", \"next\": \"fork_clone\" }, \"fork_clone\": { \"type\": \"fork_clone\", \"next\": [\"terminate\"] }, \"terminate\": { \"type\": \"terminate\" } } } # \"#)?; # Ok::<_, serde_json::Error>(())",
73+
"description": "If the request is cloneable, clone it into multiple responses.\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"start\": \"fork_clone\", \"ops\": { \"fork_clone\": { \"type\": \"fork_clone\", \"next\": [\"terminate\"] } } } # \"#)?; # Ok::<_, serde_json::Error>(())",
8174
"type": "object",
8275
"required": [
8376
"next",
@@ -87,7 +80,7 @@
8780
"next": {
8881
"type": "array",
8982
"items": {
90-
"type": "string"
83+
"$ref": "#/definitions/NextOperation"
9184
}
9285
},
9386
"type": {
@@ -99,7 +92,7 @@
9992
}
10093
},
10194
{
102-
"description": "If the request is a tuple of (T1, T2, T3, ...), unzip it into multiple responses of T1, T2, T3, ...\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"ops\": { \"start\": { \"type\": \"start\", \"next\": \"unzip\" }, \"unzip\": { \"type\": \"unzip\", \"next\": [\"terminate\"] }, \"terminate\": { \"type\": \"terminate\" } } } # \"#)?; # Ok::<_, serde_json::Error>(())",
95+
"description": "If the request is a tuple of (T1, T2, T3, ...), unzip it into multiple responses of T1, T2, T3, ...\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"start\": \"unzip\", \"ops\": { \"unzip\": { \"type\": \"unzip\", \"next\": [{ \"builtin\": \"terminate\" }] } } } # \"#)?; # Ok::<_, serde_json::Error>(())",
10396
"type": "object",
10497
"required": [
10598
"next",
@@ -109,7 +102,7 @@
109102
"next": {
110103
"type": "array",
111104
"items": {
112-
"type": "string"
105+
"$ref": "#/definitions/NextOperation"
113106
}
114107
},
115108
"type": {
@@ -121,7 +114,7 @@
121114
}
122115
},
123116
{
124-
"description": "If the request is a `Result<_, _>`, branch it to `Ok` and `Err`.\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"ops\": { \"start\": { \"type\": \"start\", \"next\": \"fork_result\" }, \"fork_result\": { \"type\": \"fork_result\", \"ok\": \"terminate\", \"err\": \"dispose\" }, \"dispose\": { \"type\": \"dispose\" }, \"terminate\": { \"type\": \"terminate\" } } } # \"#)?; # Ok::<_, serde_json::Error>(())",
117+
"description": "If the request is a `Result<_, _>`, branch it to `Ok` and `Err`.\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"start\": \"fork_result\", \"ops\": { \"fork_result\": { \"type\": \"fork_result\", \"ok\": { \"builtin\": \"terminate\" }, \"err\": { \"builtin\": \"dispose\" } } } } # \"#)?; # Ok::<_, serde_json::Error>(())",
125118
"type": "object",
126119
"required": [
127120
"err",
@@ -130,10 +123,10 @@
130123
],
131124
"properties": {
132125
"err": {
133-
"type": "string"
126+
"$ref": "#/definitions/NextOperation"
134127
},
135128
"ok": {
136-
"type": "string"
129+
"$ref": "#/definitions/NextOperation"
137130
},
138131
"type": {
139132
"type": "string",
@@ -144,7 +137,7 @@
144137
}
145138
},
146139
{
147-
"description": "If the request is a list-like or map-like object, split it into multiple responses. Note that the split output is a tuple of `(KeyOrIndex, Value)`, nodes receiving a split output should have request of that type instead of just the value type.\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"ops\": { \"start\": { \"type\": \"start\", \"next\": \"split\" }, \"split\": { \"type\": \"split\", \"index\": [\"terminate\"] }, \"terminate\": { \"type\": \"terminate\" } } } # \"#)?; # Ok::<_, serde_json::Error>(()) ```",
140+
"description": "If the request is a list-like or map-like object, split it into multiple responses. Note that the split output is a tuple of `(KeyOrIndex, Value)`, nodes receiving a split output should have request of that type instead of just the value type.\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"start\": \"split\", \"ops\": { \"split\": { \"type\": \"split\", \"index\": [{ \"builtin\": \"terminate\" }] } } } # \"#)?; # Ok::<_, serde_json::Error>(()) ```",
148141
"type": "object",
149142
"oneOf": [
150143
{
@@ -156,7 +149,7 @@
156149
"index": {
157150
"type": "array",
158151
"items": {
159-
"type": "string"
152+
"$ref": "#/definitions/NextOperation"
160153
}
161154
}
162155
},
@@ -171,7 +164,7 @@
171164
"key": {
172165
"type": "object",
173166
"additionalProperties": {
174-
"type": "string"
167+
"$ref": "#/definitions/NextOperation"
175168
}
176169
}
177170
},
@@ -183,9 +176,13 @@
183176
],
184177
"properties": {
185178
"remaining": {
186-
"type": [
187-
"string",
188-
"null"
179+
"anyOf": [
180+
{
181+
"$ref": "#/definitions/NextOperation"
182+
},
183+
{
184+
"type": "null"
185+
}
189186
]
190187
},
191188
"type": {
@@ -197,15 +194,15 @@
197194
}
198195
},
199196
{
200-
"description": "Wait for an item to be emitted from each of the inputs, then combined the oldest of each into an array.\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"ops\": { \"start\": { \"type\": \"start\", \"next\": \"split\" }, \"split\": { \"type\": \"split\", \"index\": [\"op1\", \"op2\"] }, \"op1\": { \"type\": \"node\", \"builder\": \"foo\", \"next\": \"join\" }, \"op2\": { \"type\": \"node\", \"builder\": \"bar\", \"next\": \"join\" }, \"join\": { \"type\": \"join\", \"next\": \"terminate\" }, \"terminate\": { \"type\": \"terminate\" } } } # \"#)?; # Ok::<_, serde_json::Error>(()) ```",
197+
"description": "Wait for an item to be emitted from each of the inputs, then combined the oldest of each into an array.\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"start\": \"split\", \"ops\": { \"split\": { \"type\": \"split\", \"index\": [\"op1\", \"op2\"] }, \"op1\": { \"type\": \"node\", \"builder\": \"foo\", \"next\": \"join\" }, \"op2\": { \"type\": \"node\", \"builder\": \"bar\", \"next\": \"join\" }, \"join\": { \"type\": \"join\", \"next\": { \"builtin\": \"terminate\" } } } } # \"#)?; # Ok::<_, serde_json::Error>(()) ```",
201198
"type": "object",
202199
"required": [
203200
"next",
204201
"type"
205202
],
206203
"properties": {
207204
"next": {
208-
"type": "string"
205+
"$ref": "#/definitions/NextOperation"
209206
},
210207
"type": {
211208
"type": "string",
@@ -216,7 +213,7 @@
216213
}
217214
},
218215
{
219-
"description": "If the request is serializable, transform it by running it through a [CEL](https://cel.dev/) program. The context includes a \"request\" variable which contains the request.\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"ops\": { \"start\": { \"type\": \"start\", \"next\": \"transform\" }, \"transform\": { \"type\": \"transform\", \"cel\": \"request.name\", \"next\": \"terminate\" }, \"terminate\": { \"type\": \"terminate\" } } } # \"#)?; # Ok::<_, serde_json::Error>(()) ```\n\nNote that due to how `serde_json` performs serialization, positive integers are always serialized as unsigned. In CEL, You can't do an operation between unsigned and signed so it is recommended to always perform explicit casts.\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"ops\": { \"start\": { \"type\": \"start\", \"next\": \"transform\" }, \"transform\": { \"type\": \"transform\", \"cel\": \"int(request.score) * 3\", \"next\": \"terminate\" }, \"terminate\": { \"type\": \"terminate\" } } } # \"#)?; # Ok::<_, serde_json::Error>(()) ```",
216+
"description": "If the request is serializable, transform it by running it through a [CEL](https://cel.dev/) program. The context includes a \"request\" variable which contains the request.\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"start\": \"transform\", \"ops\": { \"transform\": { \"type\": \"transform\", \"cel\": \"request.name\", \"next\": { \"builtin\": \"terminate\" } } } } # \"#)?; # Ok::<_, serde_json::Error>(()) ```\n\nNote that due to how `serde_json` performs serialization, positive integers are always serialized as unsigned. In CEL, You can't do an operation between unsigned and signed so it is recommended to always perform explicit casts.\n\n# Examples ``` # bevy_impulse::Diagram::from_json_str(r#\" { \"start\": \"transform\", \"ops\": { \"transform\": { \"type\": \"transform\", \"cel\": \"int(request.score) * 3\", \"next\": { \"builtin\": \"terminate\" } } } } # \"#)?; # Ok::<_, serde_json::Error>(()) ```",
220217
"type": "object",
221218
"required": [
222219
"cel",
@@ -228,7 +225,7 @@
228225
"type": "string"
229226
},
230227
"next": {
231-
"type": "string"
228+
"$ref": "#/definitions/NextOperation"
232229
},
233230
"type": {
234231
"type": "string",
@@ -254,6 +251,24 @@
254251
}
255252
}
256253
]
254+
},
255+
"NextOperation": {
256+
"anyOf": [
257+
{
258+
"type": "string"
259+
},
260+
{
261+
"type": "object",
262+
"required": [
263+
"builtin"
264+
],
265+
"properties": {
266+
"builtin": {
267+
"$ref": "#/definitions/BuiltinTarget"
268+
}
269+
}
270+
}
271+
]
257272
}
258273
}
259274
}

0 commit comments

Comments
 (0)