Skip to content

Commit e47da97

Browse files
allevodelvedor
authored andcommitted
Implement if/then/else (#91)
1 parent 09b1ab4 commit e47da97

File tree

3 files changed

+151
-11
lines changed

3 files changed

+151
-11
lines changed

index.js

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict'
22

33
var Ajv = require('ajv')
4+
var merge = require('deepmerge')
45

56
var uglify = null
67
var isLong
@@ -86,7 +87,7 @@ function build (schema, options) {
8687

8788
var dependencies = []
8889
var dependenciesName = []
89-
if (hasAnyOf(schema) || hasArrayOfTypes(schema)) {
90+
if (hasAnyOf(schema) || hasArrayOfTypes(schema) || hasIf(schema)) {
9091
dependencies.push(new Ajv())
9192
dependenciesName.push('ajv')
9293
}
@@ -143,6 +144,11 @@ function hasArrayOfTypes (schema) {
143144
return false
144145
}
145146

147+
function hasIf (schema) {
148+
const str = JSON.stringify(schema)
149+
return /"if":{/.test(str) && /"then":{/.test(str)
150+
}
151+
146152
function $asNull () {
147153
return 'null'
148154
}
@@ -475,21 +481,15 @@ function buildCode (schema, code, laterCode, name, externalSchema, fullSchema) {
475481
return { code: code, laterCode: laterCode }
476482
}
477483

478-
function buildObject (schema, code, name, externalSchema, fullSchema) {
479-
code += `
480-
function ${name} (obj) {
481-
var json = '{'
482-
var addComma = false
483-
`
484-
484+
function buildInnerObject (schema, name, externalSchema, fullSchema) {
485+
var laterCode = ''
486+
var code = ''
485487
if (schema.patternProperties) {
486488
code += addPatternProperties(schema, externalSchema, fullSchema)
487489
} else if (schema.additionalProperties && !schema.patternProperties) {
488490
code += addAdditionalProperties(schema, externalSchema, fullSchema)
489491
}
490492

491-
var laterCode = ''
492-
493493
if (schema.allOf) {
494494
schema.allOf.forEach((ss) => {
495495
var builtCode = buildCode(ss, code, laterCode, name, externalSchema, fullSchema)
@@ -504,6 +504,60 @@ function buildObject (schema, code, name, externalSchema, fullSchema) {
504504
laterCode = builtCode.laterCode
505505
}
506506

507+
return { code: code, laterCode: laterCode }
508+
}
509+
510+
function buildObject (schema, code, name, externalSchema, fullSchema) {
511+
code += `
512+
function ${name} (obj) {
513+
var json = '{'
514+
var addComma = false
515+
`
516+
517+
var laterCode = ''
518+
var r, merged
519+
if (schema.if && schema.then) {
520+
merged = merge(schema, schema.then)
521+
delete merged.if
522+
delete merged.then
523+
delete merged.else
524+
525+
code += `
526+
var valid = ajv.validate(${require('util').inspect(schema.if, {depth: null})}, obj)
527+
if (valid) {
528+
`
529+
530+
r = buildInnerObject(merged, name, externalSchema, fullSchema)
531+
code += r.code
532+
laterCode = r.laterCode
533+
534+
code += `
535+
}
536+
`
537+
if (schema.else) {
538+
merged = merge(schema, schema.else)
539+
delete merged.if
540+
delete merged.then
541+
delete merged.else
542+
543+
code += `
544+
else {
545+
`
546+
547+
r = buildInnerObject(merged, name, externalSchema, fullSchema)
548+
code += r.code
549+
laterCode = r.laterCode
550+
551+
code += `
552+
}
553+
`
554+
}
555+
} else {
556+
r = buildInnerObject(schema, name, externalSchema, fullSchema)
557+
code += r.code
558+
laterCode = r.laterCode
559+
}
560+
507561
// Removes the comma if is the last element of the string (in case there are not properties)
508562
code += `
509563
json += '}'

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"uglify-es": "^3.3.10"
3636
},
3737
"dependencies": {
38-
"ajv": "^6.4.0"
38+
"ajv": "^6.4.0",
39+
"deepmerge": "^2.1.0"
3940
}
4041
}

test/if-then-else.test.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
'use strict'
2+
3+
const t = require('tap')
4+
const build = require('..')
5+
6+
const schema = {
7+
'type': 'object',
8+
'properties': {
9+
'kind': { 'type': 'string', 'enum': ['foobar', 'greeting'] }
10+
},
11+
'if': {
12+
'properties': {
13+
'kind': { 'type': 'string', 'enum': ['foobar'] }
14+
}
15+
},
16+
'then': {
17+
'properties': {
18+
'foo': { 'type': 'string' },
19+
'bar': { 'type': 'number' }
20+
}
21+
},
22+
'else': {
23+
'properties': {
24+
'hi': { 'type': 'string' },
25+
'hello': { 'type': 'number' }
26+
}
27+
}
28+
}
29+
30+
t.test('if-then-else', t => {
31+
const tests = [
32+
{
33+
name: 'foobar',
34+
schema: schema,
35+
input: {
36+
kind: 'foobar',
37+
foo: 'FOO',
38+
bar: 42,
39+
hi: 'HI',
40+
hello: 'HELLO'
41+
},
42+
expected: JSON.stringify({
43+
kind: 'foobar',
44+
foo: 'FOO',
45+
bar: 42
46+
})
47+
},
48+
{
49+
name: 'greeting',
50+
schema: schema,
51+
input: {
52+
kind: 'greeting',
53+
foo: 'FOO',
54+
bar: 42,
55+
hi: 'HI',
56+
hello: 45
57+
},
58+
expected: JSON.stringify({
59+
kind: 'greeting',
60+
hi: 'HI',
61+
hello: 45
62+
})
63+
}
64+
]
65+
66+
tests.forEach(test => {
67+
t.test(test.name + ' - normal', t => {
68+
t.plan(1)
69+
70+
const stringify = build(test.schema)
71+
const serialized = stringify(test.input)
72+
t.equal(serialized, test.expected)
73+
})
74+
75+
t.test(test.name + ' - uglify', t => {
76+
t.plan(1)
77+
78+
const stringify = build(test.schema, { uglify: true })
79+
const serialized = stringify(test.input)
80+
t.equal(serialized, test.expected)
81+
})
82+
})
83+
84+
t.end()
85+
})

0 commit comments

Comments
 (0)