joi-to-json 5.0.0 → 5.0.2

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.
@@ -1,241 +1,241 @@
1
- ## Logical Relation
2
-
3
- There are some logical relation operators in Joi:
4
-
5
- * `and`
6
- * `nand`
7
- * `or`
8
- * `xor`
9
- * `oxor` (After Joi v14)
10
- * `with`
11
- * `without`
12
-
13
- For different operator, I have managed to describe them in JSON schema as below for different cases.
14
- Some named as `xxxGeneral` means it should be supported since JSON Draft 4.
15
- Some named as `xxxDraft7` means it is using some features until JSON Draft 7.
16
-
17
- Hence, if you are converting the Joi to Draft 4 or OpenAPI, the `xor` will be ignored.
18
-
19
- ### Usage
20
-
21
- By default, this feature is enabled.
22
- It can be disabled completely by passing option `{ logicalOpParser: false }` to `parse` API:
23
-
24
- `parse(joiObj, 'json', {}, { logicalOpParser: false })`
25
-
26
- It's also possible to disable one particular operator or use your own convertor if you come up with a more suitable JSON schema representation by passing options like `{ logicalOpParser: { xor: convertorFun, oxor: null } }`.
27
-
28
- The signature of the `convertorFun` is `function (schema, dependency)`. For example, the built-in `or` convertor function is:
29
-
30
- ```javascript
31
- function (schema, dependency) {
32
- schema.anyOf = _.map(dependency.peers, (peer) => {
33
- return { required: [peer] }
34
- })
35
- }
36
- ```
37
-
38
- ### OR
39
-
40
- ```javascript
41
- // At least one of a or b or c exists.
42
- // Failed on { d: 1 }
43
- const orJoi = joi.object({
44
- a: joi.string(),
45
- b: joi.number(),
46
- c: joi.boolean(),
47
- d: joi.number()
48
- }).or('a', 'b', 'c');
49
-
50
- const orSchemaGeneral = {
51
- type: 'object',
52
- anyOf: [
53
- { required: ['a'] }, { required: ['b'] }, { required: ['c'] }
54
- ],
55
- properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
56
- additionalProperties: false
57
- }
58
- ```
59
-
60
- ### AND
61
-
62
- ```javascript
63
- // Either a, b, and c All NOT exists, or all of them exists
64
- // Failed on { a: 'hi', b: 1 }
65
- const andJoi = joi.object({
66
- a: joi.string(),
67
- b: joi.number(),
68
- c: joi.boolean(),
69
- d: joi.number()
70
- }).and('a', 'b', 'c');
71
-
72
- const andSchemaGeneral = {
73
- type: 'object',
74
- oneOf: [
75
- {
76
- allOf: [
77
- {
78
- not: { required: ['a'] }
79
- },
80
- {
81
- not: { required: ['b'] }
82
- },
83
- {
84
- not: { required: ['c'] }
85
- }
86
- ]
87
- },
88
- { required: ['a', 'b', 'c'] }
89
- ],
90
- properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
91
- additionalProperties: false
92
- };
93
- ```
94
-
95
- ### NAND
96
-
97
- ```javascript
98
- // a, b, and c cannot all exist at the same time
99
- // Failed on { a: 'hi', b: 1, c: true }
100
- const nandJoi = joi.object({
101
- a: joi.string(),
102
- b: joi.number(),
103
- c: joi.boolean(),
104
- d: joi.number()
105
- }).nand('a', 'b', 'c');
106
-
107
- const nandSchemaGeneral = {
108
- type: 'object',
109
- not: { required: ['a', 'b', 'c'] },
110
- properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
111
- additionalProperties: false
112
- };
113
- ```
114
-
115
- ### XOR
116
-
117
- ```javascript
118
- // Only one of a, b and c can and must exist
119
- // Failed on { d: 1 } or { a: 'hi', b: 1 }
120
- const xorJoi = joi.object({
121
- a: joi.string(),
122
- b: joi.number(),
123
- c: joi.boolean(),
124
- d: joi.number()
125
- }).xor('a', 'b', 'c');
126
-
127
- const xorSchemaDraft7 = {
128
- type: 'object',
129
- if: { propertyNames: { enum: ['a', 'b', 'c'] }, minProperties: 2 },
130
- then: false,
131
- else: {
132
- oneOf: [
133
- {
134
- required: ['a']
135
- },
136
- {
137
- required: ['b']
138
- },
139
- {
140
- required: ['c']
141
- }
142
- ]
143
- },
144
- properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
145
- additionalProperties: false
146
- };
147
- ```
148
-
149
- ### OXOR
150
-
151
- ```javascript
152
- // Only one of a, b and c can exist but none is required
153
- // Failed on { a: 'hi', b: 1 }
154
- const oxorJoi = joi.object({
155
- a: joi.string(),
156
- b: joi.number(),
157
- c: joi.boolean(),
158
- d: joi.number()
159
- }).oxor('a', 'b', 'c');
160
-
161
- const oxorSchemaGeneral = {
162
- type: 'object',
163
- oneOf: [
164
- { required: ['a'] },
165
- { required: ['b'] },
166
- { required: ['c'] },
167
- {
168
- not: {
169
- oneOf: [
170
- { required: ['a'] },
171
- { required: ['b'] },
172
- { required: ['c'] },
173
- { required: ['a', 'b'] },
174
- { required: ['a', 'c'] },
175
- { required: ['b', 'c'] } // Combination up to 2 elements
176
- ]
177
- }
178
- }
179
- ],
180
- properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
181
- additionalProperties: false
182
- };
183
- ```
184
-
185
- ### WITH
186
-
187
- ```javascript
188
- // With d exists, both a and b must exist
189
- // Failed on { d: 1, a: '' }
190
- const withJoi = jjoi.object({
191
- a: joi.string(),
192
- b: joi.number(),
193
- c: joi.boolean(),
194
- d: joi.number()
195
- }).with('c', ['a']).with('d', ['a', 'b']);
196
-
197
- const withSchemaBeforeBefore2019 = {
198
- type: 'object',
199
- dependencies: {
200
- c: ['a'],
201
- d: ['a', 'b']
202
- },
203
- properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
204
- additionalProperties: false
205
- };
206
-
207
- const withSchemaBeforeDraft2019 = {
208
- type: 'object',
209
- dependentRequired: {
210
- c: ['a'],
211
- d: ['a', 'b']
212
- },
213
- properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
214
- additionalProperties: false
215
- };
216
- ```
217
-
218
- ### WITHOUT
219
-
220
- ```javascript
221
- // With a exists, either b or c must not exist
222
- // Failed on { a: '', b: 1 }
223
- const withoutJoi = jjoi.object({
224
- a: joi.string(),
225
- b: joi.number(),
226
- c: joi.boolean(),
227
- d: joi.number()
228
- }).without('a', ['b', 'c']);
229
-
230
- const withoutSchemaDraft7 = {
231
- type: 'object',
232
- if: { required: ['a'] },
233
- then: {
234
- not: {
235
- anyOf: [{ required: ['b'] }, { required: ['c'] }]
236
- }
237
- },
238
- properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
239
- additionalProperties: false
240
- };
241
- ```
1
+ ## Logical Relation
2
+
3
+ There are some logical relation operators in Joi:
4
+
5
+ * `and`
6
+ * `nand`
7
+ * `or`
8
+ * `xor`
9
+ * `oxor` (After Joi v14)
10
+ * `with`
11
+ * `without`
12
+
13
+ For different operator, I have managed to describe them in JSON schema as below for different cases.
14
+ Some named as `xxxGeneral` means it should be supported since JSON Draft 4.
15
+ Some named as `xxxDraft7` means it is using some features until JSON Draft 7.
16
+
17
+ Hence, if you are converting the Joi to Draft 4 or OpenAPI, the `xor` will be ignored.
18
+
19
+ ### Usage
20
+
21
+ By default, this feature is enabled.
22
+ It can be disabled completely by passing option `{ logicalOpParser: false }` to `parse` API:
23
+
24
+ `parse(joiObj, 'json', {}, { logicalOpParser: false })`
25
+
26
+ It's also possible to disable one particular operator or use your own convertor if you come up with a more suitable JSON schema representation by passing options like `{ logicalOpParser: { xor: convertorFun, oxor: null } }`.
27
+
28
+ The signature of the `convertorFun` is `function (schema, dependency)`. For example, the built-in `or` convertor function is:
29
+
30
+ ```javascript
31
+ function (schema, dependency) {
32
+ schema.anyOf = _.map(dependency.peers, (peer) => {
33
+ return { required: [peer] }
34
+ })
35
+ }
36
+ ```
37
+
38
+ ### OR
39
+
40
+ ```javascript
41
+ // At least one of a or b or c exists.
42
+ // Failed on { d: 1 }
43
+ const orJoi = joi.object({
44
+ a: joi.string(),
45
+ b: joi.number(),
46
+ c: joi.boolean(),
47
+ d: joi.number()
48
+ }).or('a', 'b', 'c');
49
+
50
+ const orSchemaGeneral = {
51
+ type: 'object',
52
+ anyOf: [
53
+ { required: ['a'] }, { required: ['b'] }, { required: ['c'] }
54
+ ],
55
+ properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
56
+ additionalProperties: false
57
+ }
58
+ ```
59
+
60
+ ### AND
61
+
62
+ ```javascript
63
+ // Either a, b, and c All NOT exists, or all of them exists
64
+ // Failed on { a: 'hi', b: 1 }
65
+ const andJoi = joi.object({
66
+ a: joi.string(),
67
+ b: joi.number(),
68
+ c: joi.boolean(),
69
+ d: joi.number()
70
+ }).and('a', 'b', 'c');
71
+
72
+ const andSchemaGeneral = {
73
+ type: 'object',
74
+ oneOf: [
75
+ {
76
+ allOf: [
77
+ {
78
+ not: { required: ['a'] }
79
+ },
80
+ {
81
+ not: { required: ['b'] }
82
+ },
83
+ {
84
+ not: { required: ['c'] }
85
+ }
86
+ ]
87
+ },
88
+ { required: ['a', 'b', 'c'] }
89
+ ],
90
+ properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
91
+ additionalProperties: false
92
+ };
93
+ ```
94
+
95
+ ### NAND
96
+
97
+ ```javascript
98
+ // a, b, and c cannot all exist at the same time
99
+ // Failed on { a: 'hi', b: 1, c: true }
100
+ const nandJoi = joi.object({
101
+ a: joi.string(),
102
+ b: joi.number(),
103
+ c: joi.boolean(),
104
+ d: joi.number()
105
+ }).nand('a', 'b', 'c');
106
+
107
+ const nandSchemaGeneral = {
108
+ type: 'object',
109
+ not: { required: ['a', 'b', 'c'] },
110
+ properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
111
+ additionalProperties: false
112
+ };
113
+ ```
114
+
115
+ ### XOR
116
+
117
+ ```javascript
118
+ // Only one of a, b and c can and must exist
119
+ // Failed on { d: 1 } or { a: 'hi', b: 1 }
120
+ const xorJoi = joi.object({
121
+ a: joi.string(),
122
+ b: joi.number(),
123
+ c: joi.boolean(),
124
+ d: joi.number()
125
+ }).xor('a', 'b', 'c');
126
+
127
+ const xorSchemaDraft7 = {
128
+ type: 'object',
129
+ if: { propertyNames: { enum: ['a', 'b', 'c'] }, minProperties: 2 },
130
+ then: false,
131
+ else: {
132
+ oneOf: [
133
+ {
134
+ required: ['a']
135
+ },
136
+ {
137
+ required: ['b']
138
+ },
139
+ {
140
+ required: ['c']
141
+ }
142
+ ]
143
+ },
144
+ properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
145
+ additionalProperties: false
146
+ };
147
+ ```
148
+
149
+ ### OXOR
150
+
151
+ ```javascript
152
+ // Only one of a, b and c can exist but none is required
153
+ // Failed on { a: 'hi', b: 1 }
154
+ const oxorJoi = joi.object({
155
+ a: joi.string(),
156
+ b: joi.number(),
157
+ c: joi.boolean(),
158
+ d: joi.number()
159
+ }).oxor('a', 'b', 'c');
160
+
161
+ const oxorSchemaGeneral = {
162
+ type: 'object',
163
+ oneOf: [
164
+ { required: ['a'] },
165
+ { required: ['b'] },
166
+ { required: ['c'] },
167
+ {
168
+ not: {
169
+ oneOf: [
170
+ { required: ['a'] },
171
+ { required: ['b'] },
172
+ { required: ['c'] },
173
+ { required: ['a', 'b'] },
174
+ { required: ['a', 'c'] },
175
+ { required: ['b', 'c'] } // Combination up to 2 elements
176
+ ]
177
+ }
178
+ }
179
+ ],
180
+ properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
181
+ additionalProperties: false
182
+ };
183
+ ```
184
+
185
+ ### WITH
186
+
187
+ ```javascript
188
+ // With d exists, both a and b must exist
189
+ // Failed on { d: 1, a: '' }
190
+ const withJoi = jjoi.object({
191
+ a: joi.string(),
192
+ b: joi.number(),
193
+ c: joi.boolean(),
194
+ d: joi.number()
195
+ }).with('c', ['a']).with('d', ['a', 'b']);
196
+
197
+ const withSchemaBeforeBefore2019 = {
198
+ type: 'object',
199
+ dependencies: {
200
+ c: ['a'],
201
+ d: ['a', 'b']
202
+ },
203
+ properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
204
+ additionalProperties: false
205
+ };
206
+
207
+ const withSchemaBeforeDraft2019 = {
208
+ type: 'object',
209
+ dependentRequired: {
210
+ c: ['a'],
211
+ d: ['a', 'b']
212
+ },
213
+ properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
214
+ additionalProperties: false
215
+ };
216
+ ```
217
+
218
+ ### WITHOUT
219
+
220
+ ```javascript
221
+ // With a exists, either b or c must not exist
222
+ // Failed on { a: '', b: 1 }
223
+ const withoutJoi = jjoi.object({
224
+ a: joi.string(),
225
+ b: joi.number(),
226
+ c: joi.boolean(),
227
+ d: joi.number()
228
+ }).without('a', ['b', 'c']);
229
+
230
+ const withoutSchemaDraft7 = {
231
+ type: 'object',
232
+ if: { required: ['a'] },
233
+ then: {
234
+ not: {
235
+ anyOf: [{ required: ['b'] }, { required: ['c'] }]
236
+ }
237
+ },
238
+ properties: { a: { type: 'string' }, b: { type: 'number' }, c: { type: 'boolean' }, d: { type: 'number' } },
239
+ additionalProperties: false
240
+ };
241
+ ```
@@ -1,74 +1,74 @@
1
- const _ = require('lodash')
2
- const JoiJsonSchemaParser = require('./json')
3
-
4
- class JoiJsonDraftSchemaParser extends JoiJsonSchemaParser {
5
- constructor(opts = {}) {
6
- super(_.merge({
7
- $schema: 'http://json-schema.org/draft-04/schema#',
8
- logicalOpParser: {
9
- xor: null,
10
- with: function (schema, dependency) {
11
- schema.dependencies = schema.dependencies || {}
12
- schema.dependencies[dependency.key] = dependency.peers
13
- },
14
- without: null
15
- }
16
- }, opts))
17
- }
18
-
19
- _isIfThenElseSupported() {
20
- return false
21
- }
22
-
23
- _setNumberFieldProperties(fieldSchema, fieldDefn) {
24
- super._setNumberFieldProperties(fieldSchema, fieldDefn)
25
-
26
- if (typeof fieldSchema.exclusiveMinimum !== 'undefined') {
27
- fieldSchema.minimum = fieldSchema.exclusiveMinimum
28
- fieldSchema.exclusiveMinimum = true
29
- }
30
- if (typeof fieldSchema.exclusiveMaximum !== 'undefined') {
31
- fieldSchema.maximum = fieldSchema.exclusiveMaximum
32
- fieldSchema.exclusiveMaximum = true
33
- }
34
-
35
- if (typeof fieldSchema.minimum !== 'undefined' && fieldSchema.minimum === fieldSchema.exclusiveMinimum) {
36
- fieldSchema.exclusiveMinimum = true
37
- }
38
- if (typeof fieldSchema.maximum !== 'undefined' && fieldSchema.maximum === fieldSchema.exclusiveMaximum) {
39
- fieldSchema.exclusiveMaximum = true
40
- }
41
- }
42
-
43
- _getLocalSchemaBasePath() {
44
- return '#/definitions'
45
- }
46
-
47
- _setArrayFieldProperties(fieldSchema, fieldDefn, definitions, level) {
48
- super._setArrayFieldProperties(fieldSchema, fieldDefn, definitions, level)
49
-
50
- delete fieldSchema.contains
51
- }
52
-
53
- _setConst(fieldSchema, fieldDefn) {
54
- super._setConst(fieldSchema, fieldDefn)
55
-
56
- if (typeof fieldSchema.const !== 'undefined') {
57
- if (fieldSchema.const === null) {
58
- fieldSchema.type = 'null'
59
- } else if (_.isArray(fieldSchema.const)) {
60
- fieldSchema.type = 'array'
61
- } else {
62
- // boolean / number / string / object
63
- fieldSchema.type = typeof fieldSchema.const
64
- if (fieldSchema.type === 'number' && Number.isInteger(fieldSchema.const)) {
65
- fieldSchema.type = 'integer'
66
- }
67
- }
68
- fieldSchema.enum = [fieldSchema.const]
69
- delete fieldSchema.const
70
- }
71
- }
72
- }
73
-
74
- module.exports = JoiJsonDraftSchemaParser
1
+ const _ = require('lodash')
2
+ const JoiJsonSchemaParser = require('./json')
3
+
4
+ class JoiJsonDraftSchemaParser extends JoiJsonSchemaParser {
5
+ constructor(opts = {}) {
6
+ super(_.merge({
7
+ $schema: 'http://json-schema.org/draft-04/schema#',
8
+ logicalOpParser: {
9
+ xor: null,
10
+ with: function (schema, dependency) {
11
+ schema.dependencies = schema.dependencies || {}
12
+ schema.dependencies[dependency.key] = dependency.peers
13
+ },
14
+ without: null
15
+ }
16
+ }, opts))
17
+ }
18
+
19
+ _isIfThenElseSupported() {
20
+ return false
21
+ }
22
+
23
+ _setNumberFieldProperties(fieldSchema, fieldDefn) {
24
+ super._setNumberFieldProperties(fieldSchema, fieldDefn)
25
+
26
+ if (typeof fieldSchema.exclusiveMinimum !== 'undefined') {
27
+ fieldSchema.minimum = fieldSchema.exclusiveMinimum
28
+ fieldSchema.exclusiveMinimum = true
29
+ }
30
+ if (typeof fieldSchema.exclusiveMaximum !== 'undefined') {
31
+ fieldSchema.maximum = fieldSchema.exclusiveMaximum
32
+ fieldSchema.exclusiveMaximum = true
33
+ }
34
+
35
+ if (typeof fieldSchema.minimum !== 'undefined' && fieldSchema.minimum === fieldSchema.exclusiveMinimum) {
36
+ fieldSchema.exclusiveMinimum = true
37
+ }
38
+ if (typeof fieldSchema.maximum !== 'undefined' && fieldSchema.maximum === fieldSchema.exclusiveMaximum) {
39
+ fieldSchema.exclusiveMaximum = true
40
+ }
41
+ }
42
+
43
+ _getLocalSchemaBasePath() {
44
+ return '#/definitions'
45
+ }
46
+
47
+ _setArrayFieldProperties(fieldSchema, fieldDefn, definitions, level) {
48
+ super._setArrayFieldProperties(fieldSchema, fieldDefn, definitions, level)
49
+
50
+ delete fieldSchema.contains
51
+ }
52
+
53
+ _setConst(fieldSchema, fieldDefn) {
54
+ super._setConst(fieldSchema, fieldDefn)
55
+
56
+ if (typeof fieldSchema.const !== 'undefined') {
57
+ if (fieldSchema.const === null) {
58
+ fieldSchema.type = 'null'
59
+ } else if (_.isArray(fieldSchema.const)) {
60
+ fieldSchema.type = 'array'
61
+ } else {
62
+ // boolean / number / string / object
63
+ fieldSchema.type = typeof fieldSchema.const
64
+ if (fieldSchema.type === 'number' && Number.isInteger(fieldSchema.const)) {
65
+ fieldSchema.type = 'integer'
66
+ }
67
+ }
68
+ fieldSchema.enum = [fieldSchema.const]
69
+ delete fieldSchema.const
70
+ }
71
+ }
72
+ }
73
+
74
+ module.exports = JoiJsonDraftSchemaParser
@@ -1,16 +1,16 @@
1
- const _ = require('lodash')
2
- const JoiJsonSchemaParser = require('./json')
3
-
4
- class JoiJsonDraftSchemaParser extends JoiJsonSchemaParser {
5
- constructor(opts = {}) {
6
- super(_.merge({
7
- $schema: 'https://json-schema.org/draft/2019-09/schema'
8
- }, opts))
9
- }
10
-
11
- _isKnownMetaKey(key) {
12
- return key === 'deprecated' || key === 'readOnly' || key === 'writeOnly'
13
- }
14
- }
15
-
16
- module.exports = JoiJsonDraftSchemaParser
1
+ const _ = require('lodash')
2
+ const JoiJsonSchemaParser = require('./json')
3
+
4
+ class JoiJsonDraftSchemaParser extends JoiJsonSchemaParser {
5
+ constructor(opts = {}) {
6
+ super(_.merge({
7
+ $schema: 'https://json-schema.org/draft/2019-09/schema'
8
+ }, opts))
9
+ }
10
+
11
+ _isKnownMetaKey(key) {
12
+ return key === 'deprecated' || key === 'readOnly' || key === 'writeOnly'
13
+ }
14
+ }
15
+
16
+ module.exports = JoiJsonDraftSchemaParser
@@ -285,7 +285,6 @@ class JoiJsonSchemaParser {
285
285
  this._setIfNotEmpty(fieldSchema, 'enum', this._getEnum(fieldDefn))
286
286
  if (fieldDefn.invalid && fieldDefn.invalid.length > 0) {
287
287
  fieldSchema.not = {
288
- type: fieldSchema.type,
289
288
  enum: fieldDefn.invalid
290
289
  }
291
290
  }
@@ -602,7 +601,7 @@ class JoiJsonSchemaParser {
602
601
 
603
602
  let ifThenStyle = this._isIfThenElseSupported()
604
603
  const styleSetting = _.remove(joiSpec.metas, (meta) => {
605
- return typeof meta['if-style'] !== undefined
604
+ return typeof meta['if-style'] !== 'undefined'
606
605
  })
607
606
 
608
607
  if (ifThenStyle && styleSetting.length > 0 && styleSetting[0]['if-style'] === false) {
@@ -1,31 +1,31 @@
1
- const _ = require('lodash')
2
- const JoiJsonSchemaParser = require('./json-draft-2019-09')
3
-
4
- class JoiOpenApiSchemaParser extends JoiJsonSchemaParser {
5
- constructor(opts = {}) {
6
- super(opts)
7
-
8
- this.$schema = undefined
9
- }
10
-
11
- parse(joiSpec, definitions = {}, level = 0) {
12
- const schema = super.parse(joiSpec, definitions, level)
13
-
14
- if (level === 0 && !_.isEmpty(definitions)) {
15
- schema.schemas = definitions
16
- }
17
- delete schema.components
18
-
19
- return schema
20
- }
21
-
22
- _getLocalSchemaBasePath() {
23
- return '#/components/schemas'
24
- }
25
-
26
- _isKnownMetaKey(key) {
27
- return key.startsWith('x-') || key === 'deprecated' || key === 'readOnly' || key === 'writeOnly'
28
- }
29
- }
30
-
31
- module.exports = JoiOpenApiSchemaParser
1
+ const _ = require('lodash')
2
+ const JoiJsonSchemaParser = require('./json-draft-2019-09')
3
+
4
+ class JoiOpenApiSchemaParser extends JoiJsonSchemaParser {
5
+ constructor(opts = {}) {
6
+ super(opts)
7
+
8
+ this.$schema = undefined
9
+ }
10
+
11
+ parse(joiSpec, definitions = {}, level = 0) {
12
+ const schema = super.parse(joiSpec, definitions, level)
13
+
14
+ if (level === 0 && !_.isEmpty(definitions)) {
15
+ schema.schemas = definitions
16
+ }
17
+ delete schema.components
18
+
19
+ return schema
20
+ }
21
+
22
+ _getLocalSchemaBasePath() {
23
+ return '#/components/schemas'
24
+ }
25
+
26
+ _isKnownMetaKey(key) {
27
+ return key.startsWith('x-') || key === 'deprecated' || key === 'readOnly' || key === 'writeOnly'
28
+ }
29
+ }
30
+
31
+ module.exports = JoiOpenApiSchemaParser
@@ -1,134 +1,134 @@
1
- const _ = require('lodash')
2
- const JoiJsonSchemaParser = require('./json-draft-04')
3
-
4
- class JoiOpenApiSchemaParser extends JoiJsonSchemaParser {
5
- constructor(opts = {}) {
6
- super(_.merge({
7
- logicalOpParser: {
8
- xor: null,
9
- with: null,
10
- without: null
11
- }
12
- }, opts))
13
-
14
- this.$schema = undefined
15
- }
16
-
17
- parse(joiSpec, definitions = {}, level = 0) {
18
- const fullSchema = super.parse(joiSpec, definitions, level)
19
- const schema = _.pickBy(fullSchema, (value, key) => isKnownKey(key))
20
-
21
- if (level === 0 && !_.isEmpty(definitions)) {
22
- schema.schemas = definitions
23
- }
24
-
25
- if (fullSchema.const) {
26
- schema.enum = [fullSchema.const]
27
- }
28
-
29
- return schema
30
- }
31
-
32
- _isIfThenElseSupported() {
33
- return false
34
- }
35
-
36
- _getLocalSchemaBasePath() {
37
- return '#/components/schemas'
38
- }
39
-
40
- _setBasicProperties(fieldSchema, fieldDefn) {
41
- super._setBasicProperties(fieldSchema, fieldDefn)
42
-
43
- if (!_.isEmpty(fieldSchema.examples)) {
44
- fieldSchema.example = fieldSchema.examples[0]
45
- }
46
- }
47
-
48
- _addNullTypeIfNullable(fieldSchema, fieldDefn) {
49
- super._addNullTypeIfNullable(fieldSchema, fieldDefn)
50
-
51
- if (fieldSchema.type === 'null') {
52
- delete fieldSchema.type
53
- fieldSchema.nullable = true
54
- } else if (_.isArray(fieldSchema.type) && fieldSchema.type.includes('null')) {
55
- _.remove(fieldSchema.type, (i) => {
56
- return i === 'null'
57
- })
58
- fieldSchema.nullable = true
59
-
60
- if (fieldSchema.type.length === 1) {
61
- fieldSchema.type = fieldSchema.type[0]
62
- }
63
- }
64
-
65
- if (_.isArray(fieldSchema.type)) {
66
- // anyOf might exist for When / Alternative case
67
- fieldSchema.anyOf = fieldSchema.anyOf || []
68
-
69
- _.forEach(fieldSchema.type, (t) => {
70
- const typeExisted = _.some(fieldSchema.anyOf, (condition) => {
71
- return condition.type === t
72
- })
73
-
74
- if (!typeExisted) {
75
- const def = { type: t }
76
- if (t === 'array') {
77
- def.items = {}
78
- }
79
- fieldSchema.anyOf.push(def)
80
- }
81
- })
82
-
83
- delete fieldSchema.type
84
- }
85
- }
86
-
87
- _isKnownMetaKey(key) {
88
- return isKnownMetaKey(key)
89
- }
90
- }
91
-
92
- function isKnownMetaKey(key) {
93
- return key.startsWith('x-') || key === 'deprecated' || key === 'readOnly' || key === 'writeOnly'
94
- }
95
-
96
- function isKnownKey(key) {
97
- const knownKeys = new Set([
98
- '$ref',
99
- 'title',
100
- 'multipleOf',
101
- 'maximum',
102
- 'exclusiveMaximum',
103
- 'minimum',
104
- 'exclusiveMinimum',
105
- 'maxLength',
106
- 'minLength',
107
- 'pattern',
108
- 'maxItems',
109
- 'minItems',
110
- 'uniqueItems',
111
- 'maxProperties',
112
- 'minProperties',
113
- 'required',
114
- 'enum',
115
- 'description',
116
- 'format',
117
- 'default',
118
- 'type',
119
-
120
- 'allOf',
121
- 'oneOf',
122
- 'anyOf',
123
- 'not',
124
- 'items',
125
- 'properties',
126
- 'additionalProperties',
127
-
128
- 'example',
129
- 'nullable'
130
- ])
131
- return knownKeys.has(key) || isKnownMetaKey(key)
132
- }
133
-
1
+ const _ = require('lodash')
2
+ const JoiJsonSchemaParser = require('./json-draft-04')
3
+
4
+ class JoiOpenApiSchemaParser extends JoiJsonSchemaParser {
5
+ constructor(opts = {}) {
6
+ super(_.merge({
7
+ logicalOpParser: {
8
+ xor: null,
9
+ with: null,
10
+ without: null
11
+ }
12
+ }, opts))
13
+
14
+ this.$schema = undefined
15
+ }
16
+
17
+ parse(joiSpec, definitions = {}, level = 0) {
18
+ const fullSchema = super.parse(joiSpec, definitions, level)
19
+ const schema = _.pickBy(fullSchema, (value, key) => isKnownKey(key))
20
+
21
+ if (level === 0 && !_.isEmpty(definitions)) {
22
+ schema.schemas = definitions
23
+ }
24
+
25
+ if (fullSchema.const) {
26
+ schema.enum = [fullSchema.const]
27
+ }
28
+
29
+ return schema
30
+ }
31
+
32
+ _isIfThenElseSupported() {
33
+ return false
34
+ }
35
+
36
+ _getLocalSchemaBasePath() {
37
+ return '#/components/schemas'
38
+ }
39
+
40
+ _setBasicProperties(fieldSchema, fieldDefn) {
41
+ super._setBasicProperties(fieldSchema, fieldDefn)
42
+
43
+ if (!_.isEmpty(fieldSchema.examples)) {
44
+ fieldSchema.example = fieldSchema.examples[0]
45
+ }
46
+ }
47
+
48
+ _addNullTypeIfNullable(fieldSchema, fieldDefn) {
49
+ super._addNullTypeIfNullable(fieldSchema, fieldDefn)
50
+
51
+ if (fieldSchema.type === 'null') {
52
+ delete fieldSchema.type
53
+ fieldSchema.nullable = true
54
+ } else if (_.isArray(fieldSchema.type) && fieldSchema.type.includes('null')) {
55
+ _.remove(fieldSchema.type, (i) => {
56
+ return i === 'null'
57
+ })
58
+ fieldSchema.nullable = true
59
+
60
+ if (fieldSchema.type.length === 1) {
61
+ fieldSchema.type = fieldSchema.type[0]
62
+ }
63
+ }
64
+
65
+ if (_.isArray(fieldSchema.type)) {
66
+ // anyOf might exist for When / Alternative case
67
+ fieldSchema.anyOf = fieldSchema.anyOf || []
68
+
69
+ _.forEach(fieldSchema.type, (t) => {
70
+ const typeExisted = _.some(fieldSchema.anyOf, (condition) => {
71
+ return condition.type === t
72
+ })
73
+
74
+ if (!typeExisted) {
75
+ const def = { type: t }
76
+ if (t === 'array') {
77
+ def.items = {}
78
+ }
79
+ fieldSchema.anyOf.push(def)
80
+ }
81
+ })
82
+
83
+ delete fieldSchema.type
84
+ }
85
+ }
86
+
87
+ _isKnownMetaKey(key) {
88
+ return isKnownMetaKey(key)
89
+ }
90
+ }
91
+
92
+ function isKnownMetaKey(key) {
93
+ return key.startsWith('x-') || key === 'deprecated' || key === 'readOnly' || key === 'writeOnly'
94
+ }
95
+
96
+ function isKnownKey(key) {
97
+ const knownKeys = new Set([
98
+ '$ref',
99
+ 'title',
100
+ 'multipleOf',
101
+ 'maximum',
102
+ 'exclusiveMaximum',
103
+ 'minimum',
104
+ 'exclusiveMinimum',
105
+ 'maxLength',
106
+ 'minLength',
107
+ 'pattern',
108
+ 'maxItems',
109
+ 'minItems',
110
+ 'uniqueItems',
111
+ 'maxProperties',
112
+ 'minProperties',
113
+ 'required',
114
+ 'enum',
115
+ 'description',
116
+ 'format',
117
+ 'default',
118
+ 'type',
119
+
120
+ 'allOf',
121
+ 'oneOf',
122
+ 'anyOf',
123
+ 'not',
124
+ 'items',
125
+ 'properties',
126
+ 'additionalProperties',
127
+
128
+ 'example',
129
+ 'nullable'
130
+ ])
131
+ return knownKeys.has(key) || isKnownMetaKey(key)
132
+ }
133
+
134
134
  module.exports = JoiOpenApiSchemaParser
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "joi-to-json",
3
- "version": "5.0.0",
3
+ "version": "5.0.2",
4
4
  "description": "joi to JSON / OpenAPI Schema Converter",
5
5
  "main": "index.js",
6
6
  "repository": {