@@ -37,7 +37,7 @@ let rules = [{
37
37
event : {
38
38
type: " remove" ,
39
39
params: {
40
- fields : [ " password" ]
40
+ field : " password"
41
41
},
42
42
}
43
43
}];
@@ -60,11 +60,42 @@ engine
60
60
61
61
```
62
62
63
- ## Schema and rules validation on construction
63
+ Rules engine expects to know all the rules in advance, it effectively drops builder pattern, but keeps the interface.
64
+
65
+ ## Validation
64
66
65
67
In order to prevent most common errors, ` Engine ` does initial validation on the schema, during construction.
66
- If no ` schema ` is provided to the constructor
68
+ Validation is done automatically if you specify ` schema ` during construction.
69
+
70
+ ``` js
71
+ let rules = [{
72
+ conditions: {
73
+ firstName: " empty"
74
+ },
75
+ event : {
76
+ type: " remove" ,
77
+ params: { field: " password" },
78
+ }
79
+ }];
80
+
81
+ let schema = {
82
+ properties: {
83
+ firstName: { type: " string" },
84
+ lastName: { type: " string" }
85
+ }
86
+ }
87
+
88
+ let engine = new Engine (rules, schema);
89
+ ```
90
+ ### Types of errors
91
+
92
+ - Conditions field validation (conditions use fields that are not part of the schema)
93
+ - Predicate validation (used predicates are not part of the
94
+ [ predicates] ( https://github.com/landau/predicate ) library and most likely wrong)
95
+
96
+ Validation is done only during development, validation is disabled by default in ` production ` .
67
97
98
+ WARNING!!! Currently validation does not support nested structures, so be extra careful, when using those.
68
99
69
100
## Conditional logic
70
101
@@ -73,44 +104,119 @@ with boolean logic extension.
73
104
74
105
[ Predicate] ( https://github.com/landau/predicate ) library has a lot of predicates that we found more, than sufficient for our use cases.
75
106
107
+ To showcase conditional logic, we'll be using simple ` registration ` schema
108
+
109
+ ``` js
110
+ let schema = {
111
+ definitions: {
112
+ hobby: {
113
+ type: " object" ,
114
+ properties: {
115
+ name: { type: " string" },
116
+ durationInMonth: { type: " integer" },
117
+ }
118
+ }
119
+ },
120
+ title: " A registration form" ,
121
+ description: " A simple form example." ,
122
+ type: " object" ,
123
+ required: [
124
+ " firstName" ,
125
+ " lastName"
126
+ ],
127
+ properties: {
128
+ firstName: {
129
+ type: " string" ,
130
+ title: " First name"
131
+ },
132
+ lastName: {
133
+ type: " string" ,
134
+ title: " Last name"
135
+ },
136
+ age: {
137
+ type: " integer" ,
138
+ title: " Age" ,
139
+ },
140
+ bio: {
141
+ type: " string" ,
142
+ title: " Bio" ,
143
+ },
144
+ country: {
145
+ type: " string" ,
146
+ title: " Country"
147
+ },
148
+ state: {
149
+ type: " string" ,
150
+ title: " State"
151
+ },
152
+ zip: {
153
+ type: " string" ,
154
+ title: " ZIP"
155
+ },
156
+ password: {
157
+ type: " string" ,
158
+ title: " Password" ,
159
+ minLength: 3
160
+ },
161
+ telephone: {
162
+ type: " string" ,
163
+ title: " Telephone" ,
164
+ minLength: 10
165
+ },
166
+ work: { " $ref" : " #/definitions/hobby" },
167
+ hobbies: {
168
+ type: " array" ,
169
+ items: { " $ref" : " #/definitions/hobby" }
170
+ }
171
+ }
172
+ }
173
+ ```
174
+ Assuming action part is taken from [ react-jsonschema-form-conditionals] ( https://github.com/RxNT/react-jsonschema-form-conditionals )
175
+
76
176
### Single line conditionals
77
177
78
- Let's say we need to ` remove ` ` password ` , when ` firstName ` is missing, this can be expressed like this:
178
+ Let's say we want to ` remove ` ` password ` , when ` firstName ` is missing, we can expressed it like this:
79
179
80
180
``` js
81
181
let rules = [{
82
182
conditions: {
83
183
firstName: " empty"
84
184
},
85
185
event : {
86
- type: " remove" ,
87
- params: { fields: [ " password" ] },
186
+ type: " remove" ,
187
+ params: {
188
+ field: " password"
189
+ }
88
190
}
89
191
}]
90
192
```
91
193
92
194
This translates into -
93
- when ` firstName ` is ` empty ` , perform ` remove ` of ` password ` , pretty straightforward .
195
+ when ` firstName ` is ` empty ` , trigger ` remove ` ` event ` .
94
196
95
197
` Empty ` keyword is [ equal in predicate library] ( https://landau.github.io/predicate/#equal ) and required
96
- action will be performed only when ` predicate.empty(registration.firstName) ` is ` true ` .
198
+ event will be performed only when ` predicate.empty(registration.firstName) ` is ` true ` .
97
199
98
200
### Conditionals with arguments
99
201
100
- Let's say we need to ` remove ` ` telephone ` , when ` age ` is ` less ` than ` 5 `
202
+ Let's say we need to ` require ` ` zip ` , when ` age ` is ` less ` than ` 16 ` ,
203
+ because the service we are using is legal only after ` 16 ` in some countries
101
204
102
205
``` js
103
206
let rules = [{
104
- conditions: { age: { less : 5 } },
207
+ conditions: {
208
+ age: { less : 16 }
209
+ },
105
210
event : {
106
- type: " remove" ,
107
- params: { fields: [ " telephone" ] }
211
+ type: " require" ,
212
+ params: {
213
+ field: " zip"
214
+ }
108
215
}
109
216
}]
110
217
```
111
218
112
- This translates into -
113
- when ` age ` is ` less ` than 5, ` remove ` ` telephone ` field from the schema.
219
+ This translates into - when ` age ` is ` less ` than ` 16 ` , ` require ` zip.
114
220
115
221
[ Less] ( https://landau.github.io/predicate/#less ) keyword is [ less in predicate] ( https://landau.github.io/predicate/#less ) and required
116
222
event will be returned only when ` predicate.empty(registration.age, 5) ` is ` true ` .
@@ -121,73 +227,80 @@ event will be returned only when `predicate.empty(registration.age, 5)` is `true
121
227
122
228
For the field AND is a default behavior.
123
229
124
- Looking at previous rule, we decide that we want to change the rule and ` remove ` a ` telephone ` ,
125
- when ` age ` is between ` 5 ` and ` 70 ` , so it would be available only to people older, than ` 70 ` and younger than ` 5 ` .
230
+ Looking at previous rule, we decide that we want to change the rule and ` require ` ` zip ` ,
231
+ when ` age ` is between ` 16 ` and ` 70 ` , so it would be available
232
+ only to people older, than ` 16 ` and younger than ` 70 ` .
126
233
127
234
``` js
128
235
let rules = [{
129
236
conditions: {
130
237
age: {
131
- greater: 5 ,
238
+ greater: 16 ,
132
239
less : 70 ,
133
240
}
134
241
},
135
242
event : {
136
- type: " remove" ,
137
- params: { fields: [ " telephone" ] }
243
+ type: " require" ,
244
+ params: {
245
+ field: " zip"
246
+ }
138
247
}
139
248
}]
140
249
```
141
250
142
251
By default action will be applied only when both field conditions are true.
143
- In this case, when age is ` greater ` than 5 and ` less ` than 70 .
252
+ In this case, when age is ` greater ` than ` 16 ` and ` less ` than ` 70 ` .
144
253
145
254
#### NOT
146
255
147
- Let's say we want to change the logic to opposite, and remove telephone when
148
- age is greater, ` less ` er then ` 5 ` or ` greater ` than ` 70 ` ,
256
+ Let's say we want to change the logic to opposite, and trigger event only when
257
+ ` age ` is ` less ` er then ` 16 ` or ` greater ` than ` 70 ` ,
149
258
150
259
``` js
151
260
let rules = [{
152
261
conditions: {
153
262
age: {
154
263
not: {
155
- greater: 5 ,
264
+ greater: 16 ,
156
265
less : 70 ,
157
266
}
158
267
}
159
268
},
160
269
event : {
161
- type: " remove" ,
162
- params: { fields: " telephone" }
270
+ type: " require" ,
271
+ params: {
272
+ field: " zip"
273
+ }
163
274
}
164
275
}]
165
276
```
166
277
167
- This does it, since the final result will be opposite of the previous result .
278
+ This does it, since the final result will be opposite of the previous condition .
168
279
169
280
#### OR
170
281
171
- The previous example works, but it's a bit hard to understand, luckily we can express it in more natural way
282
+ The previous example works, but it's a bit hard to understand, luckily we can express it differently
172
283
with ` or ` conditional.
173
284
174
285
``` js
175
286
let rules = [{
176
287
conditions: { age: {
177
288
or: [
178
- { less : 5 },
179
- { greater : 70 }
289
+ { lessEq : 5 },
290
+ { greaterEq : 70 }
180
291
]
181
292
}
182
293
},
183
294
event : {
184
- type: " remove" ,
185
- params: { fields: " telephone" }
295
+ type: " require" ,
296
+ params: {
297
+ field: " zip"
298
+ }
186
299
}
187
300
}]
188
301
```
189
302
190
- This is the same as ` NOT ` , but easier to grasp.
303
+ The result is the same as ` NOT ` , but easier to grasp.
191
304
192
305
### Boolean operations on multi fields
193
306
@@ -196,7 +309,7 @@ multi fields boolean operations.
196
309
197
310
#### Default AND operation
198
311
199
- Let's say we want to ` require ` ` bio ` , when ` age ` is less than 70 and ` country ` is ` USA `
312
+ Let's say, when ` age ` is less than 70 and ` country ` is ` USA ` we want to ` require ` ` bio ` .
200
313
201
314
``` js
202
315
let rules = [{
@@ -266,9 +379,30 @@ let rules = [{
266
379
267
380
### Nested object queries
268
381
382
+ Rules engine supports querying inside nested objects, with [ selectn] ( https://github.com/wilmoore/selectn.js ) ,
383
+ any data query that works in [ selectn] ( https://github.com/wilmoore/selectn.js ) , will work in here
384
+
385
+ Let's say we need to require ` state ` , when ` work ` has a ` name ` ` congressman ` , this is how we can do this:
386
+
387
+ ``` js
388
+ let rules = [{
389
+ conditions: {
390
+ " work.name" : {
391
+ name: { equals: " congressman" },
392
+ }
393
+ },
394
+ event : {
395
+ type: " require" ,
396
+ params: { fields: [ " state" ]}
397
+ }
398
+ }]
399
+ ```
400
+
401
+ ### Nested arrays object queries
402
+
269
403
Sometimes we need to make changes to the form if some nested condition is true.
270
404
271
- For example if one of the ` hobbies ` is " baseball", make ` state ` ` required ` .
405
+ For example if one of the ` hobbies ` is ` baseball ` , we need to make ` state ` ` required ` .
272
406
This can be expressed like this:
273
407
274
408
``` js
@@ -285,10 +419,7 @@ let rules = [{
285
419
}]
286
420
```
287
421
288
- ## Contribute
289
-
290
- - Issue Tracker: github.com/RxNT/json-rules-engine-simplified/issues
291
- - Source Code: github.com/RxNT/json-rules-engine-simplified
422
+ Rules engine will go through all the elements in the array and trigger ` require ` if ` any ` of the elements meet the criteria
292
423
293
424
## Support
294
425
@@ -297,5 +428,4 @@ We have a mailing list located at: ...
297
428
298
429
## License
299
430
300
- The project is licensed under the ... license.
301
-
431
+ The project is licensed under the Apache Licence 2.0.
0 commit comments