joi-to-json 1.5.0 → 2.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/README.md +34 -13
- package/index.js +41 -22
- package/lib/convertors/v12.js +241 -0
- package/lib/convertors/v13.js +9 -0
- package/lib/convertors/v14.js +24 -0
- package/lib/convertors/v15.js +9 -0
- package/lib/convertors/v16.js +30 -0
- package/lib/convertors/v17.js +9 -0
- package/lib/parsers/json-draft-04.js +17 -0
- package/lib/parsers/json-draft-2019-09.js +22 -0
- package/lib/{parser_base.js → parsers/json.js} +156 -143
- package/lib/parsers/open-api.js +69 -0
- package/package.json +15 -13
- package/.eslintrc +0 -57
- package/fixtures/joi-obj-12.1.0.js +0 -65
- package/fixtures/joi-obj-13.7.0.js +0 -65
- package/fixtures/joi-obj-14.3.1.js +0 -65
- package/fixtures/joi-obj-15.1.1.js +0 -65
- package/fixtures/joi-obj-16.1.8.js +0 -73
- package/fixtures/joi-obj-17.1.0.js +0 -73
- package/lib/parser_v14.js +0 -26
- package/lib/parser_v16.js +0 -257
- package/outputs/base.json +0 -221
- package/outputs/joi-obj-16.1.8.json +0 -247
- package/outputs/joi-obj-17.1.0.json +0 -247
- package/schemas/json-schema-draft04.json +0 -150
- package/test/all.spec.js +0 -40
package/README.md
CHANGED
|
@@ -8,10 +8,23 @@ It's **The most powerful schema description language and data validator for Java
|
|
|
8
8
|
Many times, we need to utilize this schema description to produce other output, such as Swagger OpenAPI doc.
|
|
9
9
|
That is why I build [joi-route-to-swagger](https://github.com/kenspirit/joi-route-to-swagger) in the first place.
|
|
10
10
|
|
|
11
|
-
At the beginning, `joi-route-to-swagger` relies on [joi-to-json-schema](https://github.com/lightsofapollo/joi-to-json-schema/) which utilizes many joi internal api or properties. I believed there was reason. Maybe joi did not provide the `describe` api way before. But I always feel
|
|
11
|
+
At the beginning, `joi-route-to-swagger` relies on [joi-to-json-schema](https://github.com/lightsofapollo/joi-to-json-schema/) which utilizes many joi internal api or properties. I believed there was reason. Maybe joi did not provide the `describe` api way before. But I always feel uncomfortable and think it's time to move on.
|
|
12
12
|
|
|
13
|
-
The intention of `joi-to-json` is to support converting different version's joi schema to [JSON Schema
|
|
13
|
+
The intention of `joi-to-json` is to support converting different version's joi schema to [JSON Schema](https://json-schema.org) using `describe` api.
|
|
14
14
|
|
|
15
|
+
## 2.0.0 is out
|
|
16
|
+
|
|
17
|
+
It's a breaking change.
|
|
18
|
+
|
|
19
|
+
* Functionally, output format supports OpenAPI Schema other than purely JSON Schema.
|
|
20
|
+
|
|
21
|
+
* Technically, implementation theory has a big change:
|
|
22
|
+
- In v1.0.0, it directly converts `joi.describe()` to JSON schema using different parser implementations.
|
|
23
|
+
- In v2.0.0, `joi.describe()` of different versions are first converted to one base format, the latest version of `joi.describe()` output. Then different parsers (JSON, OpenAPI) all refer to this base format.
|
|
24
|
+
|
|
25
|
+
* The benefits of the change are:
|
|
26
|
+
- Easier to retire old version of joi.
|
|
27
|
+
- Easier to support more output formats.
|
|
15
28
|
|
|
16
29
|
## Installation
|
|
17
30
|
|
|
@@ -28,21 +41,30 @@ The intention of `joi-to-json` is to support converting different version's joi
|
|
|
28
41
|
* @hapi/joi
|
|
29
42
|
* 15.1.1
|
|
30
43
|
* 16.1.8
|
|
31
|
-
|
|
44
|
+
* joi
|
|
45
|
+
* 17.4.2
|
|
32
46
|
|
|
33
|
-
For all above
|
|
47
|
+
For all above versions, I have tested one complex joi object [fixtures](./fixtures) which covers most of the JSON schema attributes that can be described in joi schema.
|
|
34
48
|
|
|
35
49
|
Although the versions chosen are the latest one for each major version, I believe it should be supporting other minor version as well.
|
|
36
50
|
|
|
37
51
|
|
|
38
52
|
## Usage
|
|
39
53
|
|
|
40
|
-
Only one API `
|
|
54
|
+
Only one API `parse` is available. It's signature is `parse(joiObj, type = 'json')`
|
|
41
55
|
|
|
42
|
-
|
|
56
|
+
Currently supported output types:
|
|
57
|
+
* `json` - Default. Stands for JSON Schema Draft 07
|
|
58
|
+
* `open-api` - Stands for OpenAPI Schema
|
|
59
|
+
* `json-draft-04` - Stands for JSON Schema Draft 04
|
|
60
|
+
* `json-draft-2019-09` - Stands for JSON Schema Draft 2019-09
|
|
61
|
+
|
|
62
|
+
The output schema format are in [outputs](./outputs) under specific folders for different types.
|
|
63
|
+
|
|
64
|
+
Sample code is as below:
|
|
43
65
|
|
|
44
66
|
```javascript
|
|
45
|
-
const
|
|
67
|
+
const parse = require('joi-to-json')
|
|
46
68
|
|
|
47
69
|
const joiSchema = joi.object().keys({
|
|
48
70
|
nickName: joi.string().required().min(3).max(20).example('鹄思乱想').description('Hero Nickname')
|
|
@@ -64,14 +86,15 @@ const joiSchema = joi.object().keys({
|
|
|
64
86
|
).required()).min(1).max(3).unique().description('Skills'),
|
|
65
87
|
tags: joi.array().items(joi.string().required()).length(2),
|
|
66
88
|
retired: joi.boolean().truthy('yes').falsy('no').insensitive(false),
|
|
67
|
-
certificate: joi.binary().encoding('base64')
|
|
89
|
+
certificate: joi.binary().encoding('base64'),
|
|
90
|
+
notes: joi.any().meta({ 'x-supported-lang': ['zh-CN', 'en-US'], deprecated: true })
|
|
68
91
|
})
|
|
69
92
|
|
|
70
|
-
const jsonSchema =
|
|
93
|
+
const jsonSchema = parse(joiSchema)
|
|
94
|
+
// Or parsing to OpenAPI schema through:
|
|
95
|
+
// const openApiSchema = parse(joiSchema, 'open-api')
|
|
71
96
|
```
|
|
72
97
|
|
|
73
|
-
The output json format is [here](./output.json)
|
|
74
|
-
|
|
75
98
|
## Test
|
|
76
99
|
|
|
77
100
|
>npm run test
|
|
@@ -79,8 +102,6 @@ The output json format is [here](./output.json)
|
|
|
79
102
|
You can optionally set below environment variables:
|
|
80
103
|
|
|
81
104
|
* `CASE_PATTERN=joi-obj-12` to control which version of joi obj to test
|
|
82
|
-
* `DEBUG=true` to check which version of the parser is chosen and the joi schema describe output
|
|
83
|
-
|
|
84
105
|
|
|
85
106
|
## License
|
|
86
107
|
|
package/index.js
CHANGED
|
@@ -1,23 +1,41 @@
|
|
|
1
1
|
const cmp = require('semver-compare')
|
|
2
|
-
const
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const path = require('path')
|
|
3
4
|
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
]
|
|
5
|
+
const convertorsDir = path.resolve(__dirname, './lib/convertors')
|
|
6
|
+
const parsersDir = path.resolve(__dirname, './lib/parsers')
|
|
7
|
+
const convertors = []
|
|
8
|
+
const parsers = {}
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
fs.readdirSync(convertorsDir).sort().reverse().forEach(file => {
|
|
11
|
+
if (file.endsWith('.js')) {
|
|
12
|
+
const convertor = require(`${convertorsDir}/${file}`)
|
|
13
|
+
convertors.push(convertor)
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
fs.readdirSync(parsersDir).forEach(file => {
|
|
18
|
+
if (file.endsWith('.js')) {
|
|
19
|
+
const parser = require(`${parsersDir}/${file}`)
|
|
20
|
+
parsers[file.split('.')[0]] = parser
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
function parse(joiObj, type = 'json') {
|
|
25
|
+
if (typeof joiObj.describe !== 'function') {
|
|
26
|
+
throw new Error('Not an joi object.')
|
|
27
|
+
}
|
|
12
28
|
|
|
13
|
-
|
|
14
|
-
|
|
29
|
+
let convertor
|
|
30
|
+
|
|
31
|
+
for (let i = 0; i < convertors.length; i++) {
|
|
32
|
+
const tmpConvertor = convertors[i]
|
|
15
33
|
try {
|
|
16
|
-
let version =
|
|
17
|
-
let result = cmp(
|
|
34
|
+
let version = tmpConvertor.getVersion(joiObj)
|
|
35
|
+
let result = cmp(tmpConvertor.getSupportVersion(), version)
|
|
18
36
|
if (result <= 0) {
|
|
19
37
|
// The first parser has smaller or equal version
|
|
20
|
-
|
|
38
|
+
convertor = tmpConvertor
|
|
21
39
|
break
|
|
22
40
|
}
|
|
23
41
|
} catch (e) {
|
|
@@ -27,17 +45,18 @@ function convert(joiObj, debug) {
|
|
|
27
45
|
}
|
|
28
46
|
}
|
|
29
47
|
|
|
30
|
-
if (!
|
|
31
|
-
console.warn('No
|
|
32
|
-
|
|
48
|
+
if (!convertor) {
|
|
49
|
+
console.warn('No matched joi version convertor found, using the latest version')
|
|
50
|
+
convertor = convertors[0]
|
|
33
51
|
}
|
|
34
52
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
53
|
+
const joiBaseSpec = new convertor().toBaseSpec(joiObj.describe())
|
|
54
|
+
const parser = parsers[type]
|
|
55
|
+
if (!parser) {
|
|
56
|
+
throw new Error(`No parser is registered for ${type}`)
|
|
39
57
|
}
|
|
40
|
-
|
|
58
|
+
|
|
59
|
+
return new parser().parse(joiBaseSpec)
|
|
41
60
|
}
|
|
42
61
|
|
|
43
|
-
module.exports =
|
|
62
|
+
module.exports = parse
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
const _ = require('lodash')
|
|
2
|
+
|
|
3
|
+
class JoiSpecConvertor {
|
|
4
|
+
constructor() {}
|
|
5
|
+
|
|
6
|
+
static getVersion(joiObj) {
|
|
7
|
+
return joiObj._currentJoi.version
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
static getSupportVersion() {
|
|
11
|
+
return '12'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
_convertObject(joiObj) {
|
|
15
|
+
if (joiObj.children) {
|
|
16
|
+
joiObj.keys = joiObj.children
|
|
17
|
+
delete joiObj.children
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
_.each(joiObj.keys, (value, _key) => {
|
|
21
|
+
this.toBaseSpec(value)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
_.each(joiObj.patterns, (pattern, _idx) => {
|
|
25
|
+
this.toBaseSpec(pattern.rule)
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
_convertDate(joiObj) {
|
|
30
|
+
if (joiObj.flags.timestamp) {
|
|
31
|
+
joiObj.flags.format = joiObj.flags.timestamp
|
|
32
|
+
delete joiObj.flags.timestamp
|
|
33
|
+
delete joiObj.flags.multiplier
|
|
34
|
+
} else if (joiObj.flags.format = {}) {
|
|
35
|
+
joiObj.flags.format = 'iso'
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
_convertAlternatives(joiObj) {
|
|
40
|
+
if (joiObj.base && joiObj.base.type === 'any') {
|
|
41
|
+
// when case
|
|
42
|
+
joiObj.type = 'any'
|
|
43
|
+
joiObj.whens = joiObj.alternatives
|
|
44
|
+
|
|
45
|
+
if (joiObj.flags.presence === 'ignore') {
|
|
46
|
+
// FIXME: Not sure when this flag is set.
|
|
47
|
+
delete joiObj.flags.presence
|
|
48
|
+
}
|
|
49
|
+
if (joiObj.whens.peek) {
|
|
50
|
+
joiObj.whens.is = joiObj.whens.peek
|
|
51
|
+
delete joiObj.whens.peek
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
joiObj.whens[0] = _.mapValues(joiObj.whens[0], (value, condition) => {
|
|
55
|
+
switch (condition) {
|
|
56
|
+
case 'is':
|
|
57
|
+
this.toBaseSpec(value)
|
|
58
|
+
value.type = 'any'
|
|
59
|
+
// FIXME: Not sure when this is set.
|
|
60
|
+
value.allow.splice(0, 0, { 'override': true })
|
|
61
|
+
break
|
|
62
|
+
case 'otherwise':
|
|
63
|
+
this.toBaseSpec(value)
|
|
64
|
+
break
|
|
65
|
+
case 'then':
|
|
66
|
+
this.toBaseSpec(value)
|
|
67
|
+
break
|
|
68
|
+
case 'ref':
|
|
69
|
+
if (value.indexOf('ref:') === 0) {
|
|
70
|
+
value = {
|
|
71
|
+
path: value.replace('ref:', '').split('.')
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
break
|
|
75
|
+
}
|
|
76
|
+
return value
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
delete joiObj.alternatives
|
|
80
|
+
delete joiObj.base
|
|
81
|
+
} else {
|
|
82
|
+
joiObj.matches = _.map(joiObj.alternatives, (alternative) => {
|
|
83
|
+
return {
|
|
84
|
+
schema: this.toBaseSpec(alternative)
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
delete joiObj.alternatives
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
_convertString(joiObj) {
|
|
92
|
+
delete joiObj.options
|
|
93
|
+
|
|
94
|
+
_.each(joiObj.rules, (rule, _idx) => {
|
|
95
|
+
const name = rule.name
|
|
96
|
+
if (['min', 'max'].includes(name)) {
|
|
97
|
+
rule.args = {
|
|
98
|
+
limit: rule.arg
|
|
99
|
+
}
|
|
100
|
+
} else if (['lowercase', 'uppercase'].includes(name)) {
|
|
101
|
+
rule.name = 'case'
|
|
102
|
+
rule.args = {
|
|
103
|
+
direction: name.replace('case', '')
|
|
104
|
+
}
|
|
105
|
+
delete joiObj.flags.case
|
|
106
|
+
} else if (rule.arg) {
|
|
107
|
+
rule.args = {
|
|
108
|
+
options: rule.arg
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (name === 'regex') {
|
|
112
|
+
rule.name = 'pattern'
|
|
113
|
+
rule.args.regex = rule.arg.pattern.toString()
|
|
114
|
+
delete rule.args.options.pattern
|
|
115
|
+
}
|
|
116
|
+
delete rule.arg
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
_convertNumber(joiObj) {
|
|
121
|
+
_.each(joiObj.rules, (rule, _idx) => {
|
|
122
|
+
const name = rule.name
|
|
123
|
+
if (['positive', 'negative'].includes(name)) {
|
|
124
|
+
rule.args = {
|
|
125
|
+
sign: name
|
|
126
|
+
}
|
|
127
|
+
rule.name = 'sign'
|
|
128
|
+
}
|
|
129
|
+
if (['greater', 'less', 'min', 'max', 'precision'].includes(name)) {
|
|
130
|
+
rule.args = {
|
|
131
|
+
limit: rule.arg
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (name === 'multiple') {
|
|
135
|
+
rule.args = {
|
|
136
|
+
base: rule.arg
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
delete rule.arg
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
if (joiObj.flags.precision) {
|
|
143
|
+
delete joiObj.flags.precision
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
_convertBoolean(joiObj) {
|
|
148
|
+
if (joiObj.flags.insensitive === false) {
|
|
149
|
+
joiObj.flags.sensitive = true
|
|
150
|
+
}
|
|
151
|
+
delete joiObj.flags.insensitive
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
_convertArray(joiObj) {
|
|
155
|
+
if (joiObj.flags.sparse === false) {
|
|
156
|
+
delete joiObj.flags.sparse
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
_.each(joiObj.rules, (rule, _idx) => {
|
|
160
|
+
const name = rule.name
|
|
161
|
+
if (['min', 'max', 'length'].includes(name)) {
|
|
162
|
+
rule.args = {
|
|
163
|
+
limit: rule.arg
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
delete rule.arg
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
_.each(joiObj.items, (item, _idx) => {
|
|
170
|
+
this.toBaseSpec(item)
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
_convertExamples(_joiObj) {
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
toBaseSpec(joiObj) {
|
|
178
|
+
joiObj.flags = joiObj.flags || {}
|
|
179
|
+
|
|
180
|
+
if (joiObj.flags.allowOnly) {
|
|
181
|
+
joiObj.flags.only = joiObj.flags.allowOnly
|
|
182
|
+
delete joiObj.flags.allowOnly
|
|
183
|
+
}
|
|
184
|
+
if (joiObj.flags.allowUnknown) {
|
|
185
|
+
joiObj.flags.unknown = joiObj.flags.allowUnknown
|
|
186
|
+
delete joiObj.flags.allowUnknown
|
|
187
|
+
}
|
|
188
|
+
if (joiObj.description) {
|
|
189
|
+
joiObj.flags.description = joiObj.description
|
|
190
|
+
delete joiObj.description
|
|
191
|
+
}
|
|
192
|
+
if (joiObj.options) {
|
|
193
|
+
joiObj.preferences = joiObj.options
|
|
194
|
+
delete joiObj.options
|
|
195
|
+
}
|
|
196
|
+
if (joiObj.valids) {
|
|
197
|
+
joiObj.allow = joiObj.valids
|
|
198
|
+
delete joiObj.valids
|
|
199
|
+
}
|
|
200
|
+
if (joiObj.meta) {
|
|
201
|
+
joiObj.metas = joiObj.meta
|
|
202
|
+
delete joiObj.meta
|
|
203
|
+
}
|
|
204
|
+
delete joiObj.invalids
|
|
205
|
+
|
|
206
|
+
this._convertExamples(joiObj)
|
|
207
|
+
|
|
208
|
+
switch (joiObj.type) {
|
|
209
|
+
case 'object':
|
|
210
|
+
this._convertObject(joiObj)
|
|
211
|
+
break
|
|
212
|
+
case 'date':
|
|
213
|
+
this._convertDate(joiObj)
|
|
214
|
+
break
|
|
215
|
+
case 'alternatives':
|
|
216
|
+
this._convertAlternatives(joiObj)
|
|
217
|
+
break
|
|
218
|
+
case 'string':
|
|
219
|
+
this._convertString(joiObj)
|
|
220
|
+
break
|
|
221
|
+
case 'number':
|
|
222
|
+
this._convertNumber(joiObj)
|
|
223
|
+
break
|
|
224
|
+
case 'boolean':
|
|
225
|
+
this._convertBoolean(joiObj)
|
|
226
|
+
break
|
|
227
|
+
case 'array':
|
|
228
|
+
this._convertArray(joiObj)
|
|
229
|
+
break
|
|
230
|
+
default:
|
|
231
|
+
break
|
|
232
|
+
}
|
|
233
|
+
if (_.isEmpty(joiObj.flags)) {
|
|
234
|
+
delete joiObj.flags
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return joiObj
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
module.exports = JoiSpecConvertor
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const BaseConverter = require('./v13')
|
|
2
|
+
|
|
3
|
+
class JoiSpecConvertor extends BaseConverter {
|
|
4
|
+
static getSupportVersion() {
|
|
5
|
+
return '14'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
_convertExamples(joiObj) {
|
|
9
|
+
if (joiObj.examples && joiObj.examples.length === 1) {
|
|
10
|
+
const example = joiObj.examples[0]
|
|
11
|
+
joiObj.examples = [example.value]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
_convertNumber(joiObj) {
|
|
16
|
+
super._convertNumber(joiObj)
|
|
17
|
+
|
|
18
|
+
if (joiObj.flags) {
|
|
19
|
+
delete joiObj.flags.unsafe
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = JoiSpecConvertor
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const BaseConverter = require('./v15')
|
|
2
|
+
|
|
3
|
+
class JoiSpecConvertor extends BaseConverter {
|
|
4
|
+
static getVersion(joiObj) {
|
|
5
|
+
return joiObj.$_root.version
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
static getSupportVersion() {
|
|
9
|
+
return '16'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// All methods are overridden because the Joi v16.1.8 spec is closed to the latest version
|
|
13
|
+
_convertExamples(_joiObj) { }
|
|
14
|
+
|
|
15
|
+
_convertObject(_joiObj) { }
|
|
16
|
+
|
|
17
|
+
_convertDate(_joiObj) { }
|
|
18
|
+
|
|
19
|
+
_convertAlternatives(_joiObj) { }
|
|
20
|
+
|
|
21
|
+
_convertString(_joiObj) { }
|
|
22
|
+
|
|
23
|
+
_convertNumber(_joiObj) { }
|
|
24
|
+
|
|
25
|
+
_convertBoolean(_joiObj) { }
|
|
26
|
+
|
|
27
|
+
_convertArray(_joiObj) {}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = JoiSpecConvertor
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const _ = require('lodash')
|
|
2
|
+
const JoiJsonSchemaParser = require('./json')
|
|
3
|
+
|
|
4
|
+
class JoiOpenApiSchemaParser extends JoiJsonSchemaParser {
|
|
5
|
+
_setNumberFieldProperties(fieldSchema, fieldDefn) {
|
|
6
|
+
super._setNumberFieldProperties(fieldSchema, fieldDefn)
|
|
7
|
+
|
|
8
|
+
if (typeof fieldSchema.minimum !== 'undefined' && fieldSchema.minimum === fieldSchema.exclusiveMinimum) {
|
|
9
|
+
fieldSchema.exclusiveMinimum = true
|
|
10
|
+
}
|
|
11
|
+
if (typeof fieldSchema.maximum !== 'undefined' && fieldSchema.maximum === fieldSchema.exclusiveMaximum) {
|
|
12
|
+
fieldSchema.exclusiveMaximum = true
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = JoiOpenApiSchemaParser
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const _ = require('lodash')
|
|
2
|
+
const JoiJsonSchemaParser = require('./json')
|
|
3
|
+
|
|
4
|
+
class JoiOpenApiSchemaParser extends JoiJsonSchemaParser {
|
|
5
|
+
parse(joiSpec) {
|
|
6
|
+
const schema = super.parse(joiSpec)
|
|
7
|
+
|
|
8
|
+
if (!_.isEmpty(joiSpec.metas)) {
|
|
9
|
+
_.each(joiSpec.metas, meta => {
|
|
10
|
+
_.each(meta, (value, key) => {
|
|
11
|
+
if (key === 'deprecated') {
|
|
12
|
+
schema[key] = value
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return schema
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = JoiOpenApiSchemaParser
|