joi-to-json 4.3.2 → 5.0.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 +8 -30
- package/index.d.ts +2 -2
- package/index.js +1 -39
- package/lib/parsers/json.js +32 -5
- package/package.json +8 -13
- package/lib/convertors/v12.js +0 -330
- package/lib/convertors/v13.js +0 -9
- package/lib/convertors/v14.js +0 -27
- package/lib/convertors/v15.js +0 -9
- package/lib/convertors/v16.js +0 -32
- package/lib/convertors/v17.js +0 -9
package/README.md
CHANGED
|
@@ -10,31 +10,16 @@ That is why I build [joi-route-to-swagger](https://github.com/kenspirit/joi-rout
|
|
|
10
10
|
|
|
11
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. Maybe joi did not provide the `describe` api way before, but I always feel uncomfortable of relying on internal api.
|
|
12
12
|
|
|
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
|
-
|
|
15
|
-
The implementation of this JOI to JSON conversion tool is simply a pipeline of two components:
|
|
16
|
-
|
|
17
|
-
1. Convertors
|
|
18
|
-
- Each JOI version has one convertor implementation.
|
|
19
|
-
- It converts the `joi.describe()` output to the baseline format (currently the v16 and v17 one)
|
|
20
|
-
|
|
21
|
-
2. Parsers
|
|
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, the baseline format.
|
|
22
14
|
- Each supported output JSON format (e.g. JSON Draft 07, OpenAPI) has one parser implementation.
|
|
23
15
|
- All parsers converts the baseline format into its own format
|
|
24
16
|
|
|
25
17
|
|
|
26
18
|
## Joi Version Support
|
|
27
19
|
|
|
28
|
-
* @commercial/joi
|
|
29
|
-
* v12.1.0
|
|
30
20
|
* joi
|
|
31
|
-
* 13.
|
|
32
|
-
*
|
|
33
|
-
* @hapi/joi
|
|
34
|
-
* 15.1.1
|
|
35
|
-
* 16.1.8
|
|
36
|
-
* joi
|
|
37
|
-
* 17.9.2
|
|
21
|
+
* 17.13.3
|
|
22
|
+
* 18.0.0
|
|
38
23
|
|
|
39
24
|
Although the versions chosen are the latest one for each major version, It should support other minor versions as well.
|
|
40
25
|
|
|
@@ -300,16 +285,13 @@ parse(joi.string(), 'open-api', {}, { logicalOpParser }); // Partially override
|
|
|
300
285
|
|
|
301
286
|
* JOI Standard Representation Conversion
|
|
302
287
|
|
|
303
|
-
`fixtures-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
Standard converted results are stored in `outputs-conversion` folder.
|
|
307
|
-
|
|
308
|
-
`test/conversion.spec.js` Test Spec handles all supported JOI versions' conversion verificaiton.
|
|
288
|
+
`fixtures-baseline` folder stores JOI schema definition for different data types.
|
|
289
|
+
`outputs-baseline` folder stores expected output for `describe()` api for schemas in `fixtures-baseline` folder.
|
|
290
|
+
`test/conversion.spec.js` Test Spec verifies expected output for `describe()` api for schemas in `fixtures-baseline` folder.
|
|
309
291
|
|
|
310
292
|
* JSON output format Conversion
|
|
311
293
|
|
|
312
|
-
`outputs-parsers` folder stores different output formats base on the JOI Standard Representation in `outputs-
|
|
294
|
+
`outputs-parsers` folder stores different output formats base on the JOI Standard Representation in `outputs-baseline` folder.
|
|
313
295
|
The Test Spec under `test/parser/` are responsible for these area.
|
|
314
296
|
|
|
315
297
|
* JSON schema (Draft 07) Validity Unit Test
|
|
@@ -321,12 +303,8 @@ For special **Logical Relation Operator** and **Conditional Expression**, some U
|
|
|
321
303
|
|
|
322
304
|
When running `conversion.spec.js`, below environment variables can be set:
|
|
323
305
|
|
|
324
|
-
* `
|
|
325
|
-
Example: `TEST_CONVERTOR=v17`
|
|
326
|
-
* `TEST_CASE`: control which test cases to verify. Name of the test cases is the key of the return object in `fixtures-conversion`.
|
|
306
|
+
* `TEST_CASE`: control which test cases to verify. Name of the test cases is the key of the return object in `fixtures-baseline`.
|
|
327
307
|
Example: `TEST_CASE=conditional,match_all` verifies the case in `alternatives.js`
|
|
328
|
-
* `TEST_UPDATE_CONVERSION_BASELINE`: control whether writes the baseline file generated from the latest-version convertor (Currently `v17`).
|
|
329
|
-
It is activated when setting to `true`.
|
|
330
308
|
|
|
331
309
|
When runninng Test Spec under `test/parser`, below environment variables can be set:
|
|
332
310
|
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Joi from 'joi
|
|
1
|
+
import Joi from 'joi';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @type {string}
|
|
@@ -20,7 +20,7 @@ export interface LogicalOpParserOpts {
|
|
|
20
20
|
oxor?: LogicalOpParserFn,
|
|
21
21
|
with?: LogicalOpParserFn,
|
|
22
22
|
without?: LogicalOpParserFn
|
|
23
|
-
}
|
|
23
|
+
}
|
|
24
24
|
|
|
25
25
|
export type ParserOptions = false | { logicalOpParser?: LogicalOpParserOpts };
|
|
26
26
|
|
package/index.js
CHANGED
|
@@ -1,21 +1,9 @@
|
|
|
1
|
-
const cmp = require('semver-compare')
|
|
2
|
-
|
|
3
|
-
const c17 = require('./lib/convertors/v17')
|
|
4
|
-
const c16 = require('./lib/convertors/v16')
|
|
5
|
-
const c15 = require('./lib/convertors/v15')
|
|
6
|
-
const c14 = require('./lib/convertors/v14')
|
|
7
|
-
const c13 = require('./lib/convertors/v13')
|
|
8
|
-
const c12 = require('./lib/convertors/v12')
|
|
9
|
-
|
|
10
1
|
const JoiJsonSchemaParser = require('./lib/parsers/json')
|
|
11
2
|
const JoiOpenApiSchemaParser = require('./lib/parsers/open-api')
|
|
12
3
|
const JoiOpenApiThreePointOneSchemaParser = require('./lib/parsers/open-api-3.1')
|
|
13
4
|
const JoiJsonDraftSchemaParser19 = require('./lib/parsers/json-draft-2019-09')
|
|
14
5
|
const JoiJsonDraftSchemaParser = require('./lib/parsers/json-draft-04')
|
|
15
6
|
|
|
16
|
-
const convertors = [
|
|
17
|
-
c17, c16, c15, c14, c13, c12
|
|
18
|
-
]
|
|
19
7
|
const parsers = {
|
|
20
8
|
'json-draft-2019-09': JoiJsonDraftSchemaParser19,
|
|
21
9
|
'json-draft-04': JoiJsonDraftSchemaParser,
|
|
@@ -29,33 +17,7 @@ function parse(joiObj, type = 'json', definitions = {}, parserOptions = {}) {
|
|
|
29
17
|
throw new Error('Not an joi object.')
|
|
30
18
|
}
|
|
31
19
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
for (let i = 0; i < convertors.length; i++) {
|
|
35
|
-
const tmpConvertor = convertors[i]
|
|
36
|
-
try {
|
|
37
|
-
let version = tmpConvertor.getVersion(joiObj)
|
|
38
|
-
let result = cmp(tmpConvertor.getSupportVersion(), version)
|
|
39
|
-
if (result <= 0) {
|
|
40
|
-
// The first parser has smaller or equal version
|
|
41
|
-
convertor = tmpConvertor
|
|
42
|
-
break
|
|
43
|
-
}
|
|
44
|
-
} catch (e) {
|
|
45
|
-
// Format does not match this parser version.
|
|
46
|
-
// Skip to check the next one
|
|
47
|
-
continue
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (!convertor) {
|
|
52
|
-
console.warn('No matched joi version convertor found, using the latest version')
|
|
53
|
-
convertor = convertors[0]
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// fs.writeFileSync('./joi_spec.json', JSON.stringify(joiObj.describe(), null, 2))
|
|
57
|
-
const joiBaseSpec = new convertor().toBaseSpec(joiObj.describe())
|
|
58
|
-
// fs.writeFileSync(`./internal_${convertor.getSupportVersion()}_${type}.json`, JSON.stringify(joiBaseSpec, null, 2))
|
|
20
|
+
const joiBaseSpec = joiObj.describe()
|
|
59
21
|
const parser = parsers[type]
|
|
60
22
|
if (!parser) {
|
|
61
23
|
throw new Error(`No parser is registered for ${type}`)
|
package/lib/parsers/json.js
CHANGED
|
@@ -89,6 +89,7 @@ class JoiJsonSchemaParser {
|
|
|
89
89
|
this.ruleArgFieldName = this._getRuleArgFieldName()
|
|
90
90
|
this.enumFieldName = this._getEnumFieldName()
|
|
91
91
|
this.allowUnknownFlagName = this._getAllowUnknownFlagName()
|
|
92
|
+
this.inheritedPreferences = []
|
|
92
93
|
|
|
93
94
|
if (opts.logicalOpParser === false) {
|
|
94
95
|
this.logicalOpParser = {}
|
|
@@ -100,7 +101,12 @@ class JoiJsonSchemaParser {
|
|
|
100
101
|
parse(joiSpec, definitions = {}, level = 0) {
|
|
101
102
|
let schema = {}
|
|
102
103
|
|
|
104
|
+
const hasPreferences = this._pushInheritiedPreferences(joiSpec)
|
|
105
|
+
|
|
103
106
|
if (this._getPresence(joiSpec) === 'forbidden') {
|
|
107
|
+
if (hasPreferences) {
|
|
108
|
+
this._popInheritiedPreferences()
|
|
109
|
+
}
|
|
104
110
|
schema.not = {}
|
|
105
111
|
return schema
|
|
106
112
|
}
|
|
@@ -143,9 +149,28 @@ class JoiJsonSchemaParser {
|
|
|
143
149
|
schema.$schema = this.$schema
|
|
144
150
|
}
|
|
145
151
|
|
|
152
|
+
if (hasPreferences) {
|
|
153
|
+
this._popInheritiedPreferences()
|
|
154
|
+
}
|
|
146
155
|
return schema
|
|
147
156
|
}
|
|
148
157
|
|
|
158
|
+
_pushInheritiedPreferences(joiSpec) {
|
|
159
|
+
if (joiSpec.preferences) {
|
|
160
|
+
this.inheritedPreferences.push(_.merge({}, this._getInheritedPreferences(), joiSpec.preferences))
|
|
161
|
+
return true
|
|
162
|
+
}
|
|
163
|
+
return false
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
_popInheritiedPreferences() {
|
|
167
|
+
this.inheritedPreferences.pop()
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
_getInheritedPreferences() {
|
|
171
|
+
return this.inheritedPreferences[this.inheritedPreferences.length - 1] || {}
|
|
172
|
+
}
|
|
173
|
+
|
|
149
174
|
_isIfThenElseSupported() {
|
|
150
175
|
return true
|
|
151
176
|
}
|
|
@@ -216,7 +241,8 @@ class JoiJsonSchemaParser {
|
|
|
216
241
|
if (presence !== undefined) {
|
|
217
242
|
return presence
|
|
218
243
|
}
|
|
219
|
-
|
|
244
|
+
const preferences = fieldDefn[this.optionsFieldName] || this._getInheritedPreferences()
|
|
245
|
+
return _.get(preferences, 'presence')
|
|
220
246
|
}
|
|
221
247
|
|
|
222
248
|
_isRequired(fieldDefn) {
|
|
@@ -237,11 +263,12 @@ class JoiJsonSchemaParser {
|
|
|
237
263
|
}
|
|
238
264
|
|
|
239
265
|
_getUnknown(joiSpec) {
|
|
240
|
-
|
|
241
|
-
if (
|
|
242
|
-
allowUnknown
|
|
266
|
+
const allowUnknown = _.get(joiSpec, `flags.${this.allowUnknownFlagName}`)
|
|
267
|
+
if (allowUnknown !== undefined) {
|
|
268
|
+
return allowUnknown
|
|
243
269
|
}
|
|
244
|
-
|
|
270
|
+
const preferences = joiSpec[this.optionsFieldName] || this._getInheritedPreferences()
|
|
271
|
+
return _.get(preferences, 'allowUnknown') || false
|
|
245
272
|
}
|
|
246
273
|
|
|
247
274
|
_setIfNotEmpty(schema, field, value) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "joi-to-json",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "joi to JSON / OpenAPI Schema Converter",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -24,21 +24,16 @@
|
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"combinations": "^1.0.0",
|
|
27
|
-
"lodash": "^4.17.21"
|
|
28
|
-
"semver-compare": "^1.0.0"
|
|
27
|
+
"lodash": "^4.17.21"
|
|
29
28
|
},
|
|
30
29
|
"devDependencies": {
|
|
31
|
-
"@jest/transform": "^
|
|
32
|
-
"ajv": "^8.
|
|
30
|
+
"@jest/transform": "^30.0.5",
|
|
31
|
+
"ajv": "^8.17.1",
|
|
33
32
|
"ajv-draft-04": "^1.0.0",
|
|
34
|
-
"eslint": "^
|
|
35
|
-
"jest": "^
|
|
36
|
-
"joi
|
|
37
|
-
"
|
|
38
|
-
"joi-14": "npm:joi@^14.3.1",
|
|
39
|
-
"joi-15": "npm:@hapi/joi@^15.1.1",
|
|
40
|
-
"joi-16": "npm:@hapi/joi@^16.1.8",
|
|
41
|
-
"joi-17": "npm:joi@^17.9.2"
|
|
33
|
+
"eslint": "^9.33.0",
|
|
34
|
+
"jest": "^30.0.5",
|
|
35
|
+
"joi": "18.0.0",
|
|
36
|
+
"typescript": "^5.9.2"
|
|
42
37
|
},
|
|
43
38
|
"types": "index.d.ts",
|
|
44
39
|
"files": [
|
package/lib/convertors/v12.js
DELETED
|
@@ -1,330 +0,0 @@
|
|
|
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
|
-
_.each(joiObj.rules, (rule, _idx) => {
|
|
16
|
-
const name = rule.name
|
|
17
|
-
if (['min', 'max', 'length'].includes(name)) {
|
|
18
|
-
rule.args = {
|
|
19
|
-
limit: rule.arg
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
delete rule.arg
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
if (joiObj.children) {
|
|
26
|
-
joiObj.keys = joiObj.children
|
|
27
|
-
delete joiObj.children
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
_.each(joiObj.keys, (value, _key) => {
|
|
31
|
-
this.toBaseSpec(value)
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
_.each(joiObj.patterns, (pattern, _idx) => {
|
|
35
|
-
this.toBaseSpec(pattern.rule)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
this._convertDependencies(joiObj)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
_convertDependencies(joiObj) {
|
|
42
|
-
_.each(joiObj.dependencies, (dependency) => {
|
|
43
|
-
if (dependency.key === null) {
|
|
44
|
-
delete dependency.key
|
|
45
|
-
}
|
|
46
|
-
if (dependency.type) {
|
|
47
|
-
dependency.rel = dependency.type
|
|
48
|
-
delete dependency.type
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
_convertDate(joiObj) {
|
|
54
|
-
if (joiObj.flags.timestamp) {
|
|
55
|
-
joiObj.flags.format = joiObj.flags.timestamp
|
|
56
|
-
delete joiObj.flags.timestamp
|
|
57
|
-
delete joiObj.flags.multiplier
|
|
58
|
-
} else if (joiObj.flags.format = {}) {
|
|
59
|
-
joiObj.flags.format = 'iso'
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
_convertAlternatives(joiObj) {
|
|
64
|
-
// backup alternatives setting
|
|
65
|
-
const alternatives = joiObj.alternatives
|
|
66
|
-
let fieldName = 'matches'
|
|
67
|
-
|
|
68
|
-
if (joiObj.base) {
|
|
69
|
-
// When case is based on one schema type
|
|
70
|
-
fieldName = 'whens'
|
|
71
|
-
|
|
72
|
-
const baseType = joiObj.base
|
|
73
|
-
delete joiObj.base
|
|
74
|
-
delete joiObj.alternatives
|
|
75
|
-
if (joiObj.flags && joiObj.flags.presence) {
|
|
76
|
-
delete joiObj.flags.presence
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
this.toBaseSpec(baseType)
|
|
80
|
-
|
|
81
|
-
_.merge(joiObj, baseType)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Convert alternatives
|
|
85
|
-
joiObj[fieldName] = _.map(alternatives, (alternative) => {
|
|
86
|
-
if (alternative.peek || alternative.ref) {
|
|
87
|
-
if (alternative.peek) {
|
|
88
|
-
alternative.is = alternative.peek
|
|
89
|
-
delete alternative.peek
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return _.mapValues(alternative, (value, condition) => {
|
|
93
|
-
switch (condition) {
|
|
94
|
-
case 'is':
|
|
95
|
-
this.toBaseSpec(value)
|
|
96
|
-
if (alternative.ref) {
|
|
97
|
-
// alternative field reference case
|
|
98
|
-
value.type = 'any'
|
|
99
|
-
value.allow.splice(0, 0, { 'override': true })
|
|
100
|
-
}
|
|
101
|
-
break
|
|
102
|
-
case 'otherwise':
|
|
103
|
-
this.toBaseSpec(value)
|
|
104
|
-
break
|
|
105
|
-
case 'then':
|
|
106
|
-
this.toBaseSpec(value)
|
|
107
|
-
break
|
|
108
|
-
case 'ref':
|
|
109
|
-
if (value.indexOf('ref:') === 0) {
|
|
110
|
-
value = {
|
|
111
|
-
path: value.replace('ref:', '').split('.')
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
break
|
|
115
|
-
}
|
|
116
|
-
return value
|
|
117
|
-
})
|
|
118
|
-
} else {
|
|
119
|
-
return {
|
|
120
|
-
schema: this.toBaseSpec(alternative)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
// FIXME: Joi seems merging the `is` to `then` schema
|
|
126
|
-
_.forEach(joiObj[fieldName], (alternative) => {
|
|
127
|
-
if (alternative.is && alternative.then) {
|
|
128
|
-
if (alternative.is.type === 'object') {
|
|
129
|
-
const isKeys = Object.keys(alternative.is.keys)
|
|
130
|
-
_.forEach(isKeys, (key) => {
|
|
131
|
-
delete alternative.then.keys[key]
|
|
132
|
-
})
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
delete joiObj.alternatives
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
_convertBinary(joiObj) {
|
|
141
|
-
_.each(joiObj.rules, (rule, _idx) => {
|
|
142
|
-
const name = rule.name
|
|
143
|
-
if (['min', 'max', 'length'].includes(name)) {
|
|
144
|
-
rule.args = {
|
|
145
|
-
limit: rule.arg
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
delete rule.arg
|
|
149
|
-
})
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
_convertString(joiObj) {
|
|
153
|
-
delete joiObj.options
|
|
154
|
-
|
|
155
|
-
_.each(joiObj.rules, (rule, _idx) => {
|
|
156
|
-
const name = rule.name
|
|
157
|
-
if (['min', 'max'].includes(name)) {
|
|
158
|
-
rule.args = {
|
|
159
|
-
limit: rule.arg
|
|
160
|
-
}
|
|
161
|
-
} else if (['lowercase', 'uppercase'].includes(name)) {
|
|
162
|
-
rule.name = 'case'
|
|
163
|
-
rule.args = {
|
|
164
|
-
direction: name.replace('case', '')
|
|
165
|
-
}
|
|
166
|
-
delete joiObj.flags.case
|
|
167
|
-
} else if (rule.arg) {
|
|
168
|
-
rule.args = {
|
|
169
|
-
options: rule.arg
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
if (name === 'regex') {
|
|
173
|
-
rule.name = 'pattern'
|
|
174
|
-
rule.args.regex = rule.arg.pattern.toString()
|
|
175
|
-
delete rule.args.options.pattern
|
|
176
|
-
}
|
|
177
|
-
delete rule.arg
|
|
178
|
-
})
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
_convertNumber(joiObj) {
|
|
182
|
-
_.each(joiObj.rules, (rule, _idx) => {
|
|
183
|
-
const name = rule.name
|
|
184
|
-
if (['positive', 'negative'].includes(name)) {
|
|
185
|
-
rule.args = {
|
|
186
|
-
sign: name
|
|
187
|
-
}
|
|
188
|
-
rule.name = 'sign'
|
|
189
|
-
}
|
|
190
|
-
if (['greater', 'less', 'min', 'max', 'precision'].includes(name)) {
|
|
191
|
-
rule.args = {
|
|
192
|
-
limit: rule.arg
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
if (name === 'multiple') {
|
|
196
|
-
rule.args = {
|
|
197
|
-
base: rule.arg
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
delete rule.arg
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
if (joiObj.flags.precision) {
|
|
204
|
-
delete joiObj.flags.precision
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
_convertBoolean(joiObj) {
|
|
209
|
-
if (_.isArray(joiObj.truthy)) {
|
|
210
|
-
_.remove(joiObj.truthy, (i) => i === true)
|
|
211
|
-
if (joiObj.truthy.length === 0) {
|
|
212
|
-
delete joiObj.truthy
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (_.isArray(joiObj.falsy)) {
|
|
216
|
-
_.remove(joiObj.falsy, (i) => i === false)
|
|
217
|
-
if (joiObj.falsy.length === 0) {
|
|
218
|
-
delete joiObj.falsy
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
if (joiObj.flags.insensitive === false) {
|
|
222
|
-
joiObj.flags.sensitive = true
|
|
223
|
-
}
|
|
224
|
-
delete joiObj.flags.insensitive
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
_convertArray(joiObj) {
|
|
228
|
-
if (joiObj.flags.sparse === false) {
|
|
229
|
-
delete joiObj.flags.sparse
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
_.each(joiObj.rules, (rule, _idx) => {
|
|
233
|
-
const name = rule.name
|
|
234
|
-
if (['min', 'max', 'length'].includes(name)) {
|
|
235
|
-
rule.args = {
|
|
236
|
-
limit: rule.arg
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
if (name === 'has') {
|
|
240
|
-
this.toBaseSpec(rule.arg)
|
|
241
|
-
rule.args = {
|
|
242
|
-
schema: rule.arg
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
delete rule.arg
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
_.each(joiObj.items, (item, _idx) => {
|
|
249
|
-
this.toBaseSpec(item)
|
|
250
|
-
})
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
_convertExamples(_joiObj) {
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
toBaseSpec(joiObj) {
|
|
257
|
-
joiObj.flags = joiObj.flags || {}
|
|
258
|
-
|
|
259
|
-
if (joiObj.flags.allowOnly) {
|
|
260
|
-
joiObj.flags.only = joiObj.flags.allowOnly
|
|
261
|
-
}
|
|
262
|
-
delete joiObj.flags.allowOnly
|
|
263
|
-
if (joiObj.flags.allowUnknown) {
|
|
264
|
-
joiObj.flags.unknown = joiObj.flags.allowUnknown
|
|
265
|
-
}
|
|
266
|
-
delete joiObj.flags.allowUnknown
|
|
267
|
-
if (joiObj.description) {
|
|
268
|
-
joiObj.flags.description = joiObj.description
|
|
269
|
-
delete joiObj.description
|
|
270
|
-
}
|
|
271
|
-
if (joiObj.options) {
|
|
272
|
-
joiObj.preferences = joiObj.options
|
|
273
|
-
delete joiObj.options
|
|
274
|
-
}
|
|
275
|
-
if (joiObj.valids) {
|
|
276
|
-
joiObj.allow = joiObj.valids
|
|
277
|
-
delete joiObj.valids
|
|
278
|
-
}
|
|
279
|
-
if (joiObj.meta) {
|
|
280
|
-
joiObj.metas = joiObj.meta
|
|
281
|
-
delete joiObj.meta
|
|
282
|
-
}
|
|
283
|
-
if (joiObj.invalids) {
|
|
284
|
-
// FIXME Looks like before v16, joi spec default add [''] for string and [Infinity,-Infinity] for number
|
|
285
|
-
if (!(joiObj.invalids.length === 1 && joiObj.invalids[0] === '') &&
|
|
286
|
-
!(joiObj.invalids.length === 2 && joiObj.invalids[0] === Infinity && joiObj.invalids[1] === -Infinity)) {
|
|
287
|
-
joiObj.invalid = joiObj.invalids
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
delete joiObj.invalids
|
|
291
|
-
|
|
292
|
-
this._convertExamples(joiObj)
|
|
293
|
-
|
|
294
|
-
switch (joiObj.type) {
|
|
295
|
-
case 'object':
|
|
296
|
-
this._convertObject(joiObj)
|
|
297
|
-
break
|
|
298
|
-
case 'date':
|
|
299
|
-
this._convertDate(joiObj)
|
|
300
|
-
break
|
|
301
|
-
case 'alternatives':
|
|
302
|
-
this._convertAlternatives(joiObj)
|
|
303
|
-
break
|
|
304
|
-
case 'binary':
|
|
305
|
-
this._convertBinary(joiObj)
|
|
306
|
-
break
|
|
307
|
-
case 'string':
|
|
308
|
-
this._convertString(joiObj)
|
|
309
|
-
break
|
|
310
|
-
case 'number':
|
|
311
|
-
this._convertNumber(joiObj)
|
|
312
|
-
break
|
|
313
|
-
case 'boolean':
|
|
314
|
-
this._convertBoolean(joiObj)
|
|
315
|
-
break
|
|
316
|
-
case 'array':
|
|
317
|
-
this._convertArray(joiObj)
|
|
318
|
-
break
|
|
319
|
-
default:
|
|
320
|
-
break
|
|
321
|
-
}
|
|
322
|
-
if (_.isEmpty(joiObj.flags)) {
|
|
323
|
-
delete joiObj.flags
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
return joiObj
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
module.exports = JoiSpecConvertor
|
package/lib/convertors/v13.js
DELETED
package/lib/convertors/v14.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
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
|
-
if (joiObj.examples && joiObj.allow && joiObj.flags && joiObj.flags.only) {
|
|
14
|
-
joiObj.examples = joiObj.allow
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
_convertNumber(joiObj) {
|
|
19
|
-
super._convertNumber(joiObj)
|
|
20
|
-
|
|
21
|
-
if (joiObj.flags) {
|
|
22
|
-
delete joiObj.flags.unsafe
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
module.exports = JoiSpecConvertor
|
package/lib/convertors/v15.js
DELETED
package/lib/convertors/v16.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
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
|
-
_convertBinary(_joiObj) { }
|
|
22
|
-
|
|
23
|
-
_convertString(_joiObj) { }
|
|
24
|
-
|
|
25
|
-
_convertNumber(_joiObj) { }
|
|
26
|
-
|
|
27
|
-
_convertBoolean(_joiObj) { }
|
|
28
|
-
|
|
29
|
-
_convertArray(_joiObj) {}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
module.exports = JoiSpecConvertor
|