Skip to content

Commit d1d1ccd

Browse files
committed
WIP if-then-else
1 parent 7edaab5 commit d1d1ccd

File tree

2 files changed

+284
-4
lines changed

2 files changed

+284
-4
lines changed

src/index.js

+36-4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ var without = require('lodash/without')
1818
var withoutArr = (arr, ...rest) => without.apply(null, [arr].concat(flatten(rest)))
1919
var isPropertyRelated = (key) => contains(propertyRelated, key)
2020
var isItemsRelated = (key) => contains(itemsRelated, key)
21+
var isConditionalRelated = (key) => contains(conditonalRelated, key)
2122
var contains = (arr, val) => arr.indexOf(val) !== -1
2223
var isEmptySchema = (obj) => (!keys(obj).length) && obj !== false && obj !== true
2324
var isSchema = (val) => isPlainObject(val) || val === true || val === false
@@ -174,9 +175,14 @@ function callGroupResolver(keys, resolverName, schemas, mergeSchemas, options, p
174175
}, {})
175176
}).filter(notUndefined), compare)
176177

177-
var related = resolverName === 'properties'
178-
? propertyRelated
179-
: itemsRelated
178+
const map = {
179+
properties: propertyRelated,
180+
items: itemsRelated,
181+
if: conditonalRelated
182+
}
183+
184+
const isIf = resolverName === 'if'
185+
const related = map[resolverName]
180186

181187
var mergers = related.reduce(function(all, key) {
182188
if (contains(schemaGroupProps, key)) {
@@ -189,6 +195,8 @@ function callGroupResolver(keys, resolverName, schemas, mergeSchemas, options, p
189195
return all
190196
}, {})
191197

198+
// console.log(mergers)
199+
192200
if (resolverName === 'items') {
193201
mergers.itemsArray = createRequiredSubMerger(mergeSchemas, 'items', parents)
194202
mergers.items = function(schemas) {
@@ -202,7 +210,11 @@ function callGroupResolver(keys, resolverName, schemas, mergeSchemas, options, p
202210
throwIncompatible(compacted, parents.concat(resolverName))
203211
}
204212

205-
return cleanupReturnValue(result)
213+
if (isIf) {
214+
return result
215+
} else {
216+
return cleanupReturnValue(result)
217+
}
206218
}
207219
}
208220

@@ -244,6 +256,7 @@ function createRequiredMetaArray(arr) {
244256

245257
var propertyRelated = ['properties', 'patternProperties', 'additionalProperties']
246258
var itemsRelated = ['items', 'additionalItems']
259+
var conditonalRelated = ['if', 'then', 'else']
247260
var schemaGroupProps = ['properties', 'patternProperties', 'definitions', 'dependencies']
248261
var schemaArrays = ['anyOf', 'oneOf']
249262
var schemaProps = [
@@ -402,6 +415,21 @@ var defaultResolvers = {
402415
if (enums.length) {
403416
return sortBy(enums)
404417
}
418+
},
419+
if(values) {
420+
// console.log(values)
421+
const allWithConditional = values.filter(schema => conditonalRelated.some(keyword => schema.hasOwnProperty(keyword)))
422+
const first = allWithConditional.shift() // base schema as base
423+
const merged = allWithConditional.reduce((all, schema) => {
424+
if (!isEmptySchema(schema)) {
425+
all.allOf = (all.allOf || []).concat(schema)
426+
}
427+
return all
428+
}, first)
429+
430+
// console.log(merged)
431+
432+
return merged
405433
}
406434
}
407435

@@ -475,6 +503,9 @@ function merger(rootSchema, options, totalSchemas) {
475503
var itemKeys = allKeys.filter(isItemsRelated)
476504
pullAll(allKeys, itemKeys)
477505

506+
var conditonalKeys = allKeys.filter(isConditionalRelated)
507+
pullAll(allKeys, conditonalKeys)
508+
478509
allKeys.forEach(function(key) {
479510
var values = getValues(schemas, key)
480511
var compacted = uniqWith(values.filter(notUndefined), compareProp(key))
@@ -521,6 +552,7 @@ function merger(rootSchema, options, totalSchemas) {
521552

522553
Object.assign(merged, callGroupResolver(propertyKeys, 'properties', schemas, mergeSchemas, options, parents))
523554
Object.assign(merged, callGroupResolver(itemKeys, 'items', schemas, mergeSchemas, options, parents))
555+
Object.assign(merged, callGroupResolver(conditonalKeys, 'if', schemas, mergeSchemas, options, parents))
524556

525557
function addToAllOf(unresolvedSchemas) {
526558
merged.allOf = mergeWithArray(merged.allOf, unresolvedSchemas)

test/specs/if-then-else.spec.js

+248
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
var chai = require('chai')
2+
var merger = require('../../src')
3+
var sinon = require('sinon')
4+
var _ = require('lodash')
5+
var expect = chai.expect
6+
var Ajv = require('ajv').default
7+
8+
var ajv = new Ajv()
9+
describe('if then else', function() {
10+
it('moves the if then else to the base schema if none there', () => {
11+
const result = merger({
12+
allOf: [{
13+
if: {
14+
required: ['prop1']
15+
},
16+
then: {},
17+
else: {}
18+
}]
19+
})
20+
21+
expect(result).to.eql({
22+
if: {
23+
required: ['prop1']
24+
},
25+
then: {},
26+
else: {}
27+
})
28+
})
29+
30+
it('does NOT move the if then else to the base schema if something already there', () => {
31+
const result = merger({
32+
if: {
33+
minimum: 5
34+
},
35+
then: {
36+
maximum: 2
37+
},
38+
else: {
39+
maximum: 10
40+
},
41+
allOf: [{
42+
if: {
43+
required: ['prop1']
44+
},
45+
then: {},
46+
else: {}
47+
}]
48+
})
49+
50+
expect(result).to.eql({
51+
if: {
52+
minimum: 5
53+
},
54+
then: {
55+
maximum: 2
56+
},
57+
else: {
58+
maximum: 10
59+
},
60+
allOf: [{
61+
if: {
62+
required: ['prop1']
63+
},
64+
then: {},
65+
else: {}
66+
}]
67+
})
68+
})
69+
70+
it('moves the unaffected keywords to the base schema', () => {
71+
const result = merger({
72+
properties: {
73+
name: {
74+
type: 'string',
75+
minLength: 3
76+
}
77+
},
78+
if: {
79+
minimum: 5
80+
},
81+
then: {
82+
maximum: 2
83+
},
84+
else: {
85+
maximum: 10
86+
},
87+
allOf: [{
88+
properties: {
89+
name: {
90+
type: 'string',
91+
minLength: 5
92+
}
93+
},
94+
if: {
95+
required: ['prop1']
96+
},
97+
then: {},
98+
else: {}
99+
}]
100+
})
101+
102+
expect(result).to.eql({
103+
properties: {
104+
name: {
105+
type: 'string',
106+
minLength: 5
107+
}
108+
},
109+
if: {
110+
minimum: 5
111+
},
112+
then: {
113+
maximum: 2
114+
},
115+
else: {
116+
maximum: 10
117+
},
118+
allOf: [{
119+
if: {
120+
required: ['prop1']
121+
},
122+
then: {},
123+
else: {}
124+
}]
125+
})
126+
})
127+
128+
it('should not move to base schema if only some keywords are not present', () => {
129+
const result = merger({
130+
else: false,
131+
allOf: [{
132+
if: {
133+
required: ['prop1']
134+
},
135+
then: {},
136+
else: {}
137+
}]
138+
})
139+
140+
expect(result).to.eql({
141+
else: false,
142+
allOf: [{
143+
if: {
144+
required: ['prop1']
145+
},
146+
then: {},
147+
else: {}
148+
}]
149+
})
150+
151+
const result2 = merger({
152+
then: false,
153+
allOf: [{
154+
if: {
155+
required: ['prop1']
156+
},
157+
then: {},
158+
else: {}
159+
}]
160+
})
161+
162+
expect(result2).to.eql({
163+
then: false,
164+
allOf: [{
165+
if: {
166+
required: ['prop1']
167+
},
168+
then: {},
169+
else: {}
170+
}]
171+
})
172+
173+
const result3 = merger({
174+
if: false,
175+
allOf: [{
176+
if: {
177+
required: ['prop1']
178+
},
179+
then: {},
180+
else: {}
181+
}]
182+
})
183+
184+
expect(result3).to.eql({
185+
if: false,
186+
allOf: [{
187+
if: {
188+
required: ['prop1']
189+
},
190+
then: {},
191+
else: {}
192+
}]
193+
})
194+
})
195+
196+
it('works with undefined value, it is as if not there. NOT the same as empty schema', () => {
197+
const result = merger({
198+
if: undefined,
199+
then: undefined,
200+
else: undefined,
201+
allOf: [{
202+
if: {
203+
required: ['prop1']
204+
},
205+
then: {},
206+
else: {}
207+
}]
208+
})
209+
210+
expect(result).to.eql({
211+
if: {
212+
required: ['prop1']
213+
},
214+
then: {},
215+
else: {}
216+
})
217+
})
218+
219+
it('removes empty allOf', () => {
220+
const result = merger({
221+
if: {
222+
required: ['prop1']
223+
},
224+
then: {},
225+
else: {},
226+
allOf: [{
227+
properties: {
228+
name: {
229+
type: 'string'
230+
}
231+
}
232+
}]
233+
})
234+
235+
expect(result).to.eql({
236+
properties: {
237+
name: {
238+
type: 'string'
239+
}
240+
},
241+
if: {
242+
required: ['prop1']
243+
},
244+
then: {},
245+
else: {}
246+
})
247+
})
248+
})

0 commit comments

Comments
 (0)