joi-to-json 4.3.0 → 4.3.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,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