joi-to-json 4.0.1 → 4.1.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.
@@ -1,330 +1,330 @@
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
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
@@ -1,32 +1,32 @@
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
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
@@ -4,6 +4,7 @@ const JoiJsonSchemaParser = require('./json')
4
4
  class JoiJsonDraftSchemaParser extends JoiJsonSchemaParser {
5
5
  constructor(opts = {}) {
6
6
  super(_.merge({
7
+ $schema: 'http://json-schema.org/draft-04/schema#',
7
8
  logicalOpParser: {
8
9
  xor: null,
9
10
  with: function (schema, dependency) {
@@ -22,6 +23,15 @@ class JoiJsonDraftSchemaParser extends JoiJsonSchemaParser {
22
23
  _setNumberFieldProperties(fieldSchema, fieldDefn) {
23
24
  super._setNumberFieldProperties(fieldSchema, fieldDefn)
24
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
+
25
35
  if (typeof fieldSchema.minimum !== 'undefined' && fieldSchema.minimum === fieldSchema.exclusiveMinimum) {
26
36
  fieldSchema.exclusiveMinimum = true
27
37
  }
@@ -2,6 +2,12 @@ const _ = require('lodash')
2
2
  const JoiJsonSchemaParser = require('./json')
3
3
 
4
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
+
5
11
  parse(joiSpec, definitions = {}, level = 0) {
6
12
  const schema = super.parse(joiSpec, definitions, level)
7
13
 
@@ -82,6 +82,8 @@ function isJoiOverride(e) {
82
82
 
83
83
  class JoiJsonSchemaParser {
84
84
  constructor(opts = {}) {
85
+ this.$schema = opts.$schema || 'http://json-schema.org/draft-07/schema#'
86
+ this.includeSchemaDialect = opts.includeSchemaDialect || false
85
87
  this.childrenFieldName = this._getChildrenFieldName()
86
88
  this.optionsFieldName = this._getOptionsFieldName()
87
89
  this.ruleArgFieldName = this._getRuleArgFieldName()
@@ -133,6 +135,10 @@ class JoiJsonSchemaParser {
133
135
  _.set(schema, `${this._getLocalSchemaBasePath().replace('#/', '').replace(/\//, '.')}`, definitions)
134
136
  }
135
137
 
138
+ if (this.includeSchemaDialect && level === 0 && this.$schema) {
139
+ schema.$schema = this.$schema
140
+ }
141
+
136
142
  return schema
137
143
  }
138
144
 
@@ -395,6 +401,13 @@ class JoiJsonSchemaParser {
395
401
  case 'multiple':
396
402
  fieldSchema.multipleOf = value.base
397
403
  break
404
+ case 'sign':
405
+ if (rule.args.sign === 'positive') {
406
+ fieldSchema.exclusiveMinimum = 0
407
+ } else if (rule.args.sign === 'negative') {
408
+ fieldSchema.exclusiveMaximum = 0
409
+ }
410
+ break
398
411
  default:
399
412
  break
400
413
  }
@@ -10,6 +10,8 @@ class JoiOpenApiSchemaParser extends JoiJsonSchemaParser {
10
10
  without: null
11
11
  }
12
12
  }, opts))
13
+
14
+ this.$schema = undefined
13
15
  }
14
16
 
15
17
  parse(joiSpec, definitions = {}, level = 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "joi-to-json",
3
- "version": "4.0.1",
3
+ "version": "4.1.0",
4
4
  "description": "joi to JSON / OpenAPI Schema Converter",
5
5
  "main": "index.js",
6
6
  "repository": {