@kravc/schema 2.3.1 → 2.3.3
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/package.json +2 -2
- package/src/Validator.js +23 -3
- package/src/Validator.spec.js +38 -0
- package/src/helpers/normalizeType.js +9 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kravc/schema",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.3",
|
|
4
4
|
"description": "Advanced JSON schema manipulation and validation library.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"JSON",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"lodash.uniq": "^4.5.0",
|
|
36
36
|
"security-context": "^4.0.0",
|
|
37
37
|
"validator": "^13.7.0",
|
|
38
|
-
"z-schema": "^5.0.
|
|
38
|
+
"z-schema": "^5.0.5"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"chai": "^4.3.4",
|
package/src/Validator.js
CHANGED
|
@@ -46,9 +46,29 @@ class Validator {
|
|
|
46
46
|
throw new Error(`Schema "${schemaId}" not found`)
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const objectJson = JSON.stringify(object)
|
|
50
|
+
const result = JSON.parse(objectJson)
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
// NOTE: Drop attributes from objects that are not defined in schema.
|
|
54
|
+
// This is bad for FE developers, as they continue to send some
|
|
55
|
+
// trash to endpoints, but good for integrations with third party
|
|
56
|
+
// services, e.g. Telegram, when you do not want to define schema
|
|
57
|
+
// for the full payload. This method currently fails for cases when
|
|
58
|
+
// attribute is defined as object or array in schema, but value is
|
|
59
|
+
// a string. In this case validation method below would catch that.
|
|
60
|
+
cleanupAttributes(result, jsonSchema, this._jsonSchemasMap)
|
|
61
|
+
|
|
62
|
+
// NOTE: Normalize method helps to integrate objects built from URLs,
|
|
63
|
+
// where types are not defined, e.g. booleans are '1', 'yes' string
|
|
64
|
+
// or numbers are '1', '2'... strings.
|
|
65
|
+
normalizeAttributes(result, jsonSchema, this._jsonSchemasMap)
|
|
66
|
+
|
|
67
|
+
} catch (error) {
|
|
68
|
+
// NOTE: Skip errors in cleanup and normalize attributes methods,
|
|
69
|
+
// validation fails for objects with invalid value types.
|
|
70
|
+
|
|
71
|
+
}
|
|
52
72
|
|
|
53
73
|
const isValid = this._engine.validate(result, jsonSchema)
|
|
54
74
|
|
package/src/Validator.spec.js
CHANGED
|
@@ -137,12 +137,50 @@ describe('Validator', () => {
|
|
|
137
137
|
expect(validInput.preferences.isNotificationEnabled).to.eql(false)
|
|
138
138
|
|
|
139
139
|
expect(() => {
|
|
140
|
+
input.preferences.isNotificationEnabled = 'NaN'
|
|
141
|
+
validInput = validator.validate(input, 'Profile')
|
|
142
|
+
expect(validInput.preferences.isNotificationEnabled).to.eql('NaN')
|
|
143
|
+
}).to.throw('"Profile" validation failed')
|
|
144
|
+
|
|
145
|
+
expect(() => {
|
|
146
|
+
input.preferences.isNotificationEnabled = 0
|
|
140
147
|
input.preferences.height = 'NaN'
|
|
141
148
|
validInput = validator.validate(input, 'Profile')
|
|
142
149
|
expect(validInput.preferences.height).to.eql('NaN')
|
|
143
150
|
}).to.throw('"Profile" validation failed')
|
|
144
151
|
})
|
|
145
152
|
|
|
153
|
+
it('throws validation error if cleanup or normalize method failed', () => {
|
|
154
|
+
const validator = new Validator(SCHEMAS)
|
|
155
|
+
|
|
156
|
+
const input = {
|
|
157
|
+
name: 'Oleksandr',
|
|
158
|
+
contactDetails: {
|
|
159
|
+
email: 'a@kra.vc'
|
|
160
|
+
},
|
|
161
|
+
favoriteItems: 'NOT_ARRAY_BUT_STRING'
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
validator.validate(input, 'Profile')
|
|
166
|
+
|
|
167
|
+
} catch (validationError) {
|
|
168
|
+
const error = validationError.toJSON()
|
|
169
|
+
|
|
170
|
+
expect(error.object).to.exist
|
|
171
|
+
expect(error.code).to.eql('ValidationError')
|
|
172
|
+
expect(error.message).to.eql('"Profile" validation failed')
|
|
173
|
+
expect(error.schemaId).to.eql('Profile')
|
|
174
|
+
|
|
175
|
+
const errorMessage = error.validationErrors[0].message
|
|
176
|
+
expect(errorMessage).to.eql('Expected type array but found type string')
|
|
177
|
+
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
throw new Error('Validation error is not thrown')
|
|
182
|
+
})
|
|
183
|
+
|
|
146
184
|
it('throws error if validation failed', () => {
|
|
147
185
|
const validator = new Validator(SCHEMAS)
|
|
148
186
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const BOOLEAN_STRING_TRUE_VALUES = ['yes', 'true', '1']
|
|
4
|
+
const BOOLEAN_STRING_FALSE_VALUES = ['no', 'false', '0']
|
|
5
|
+
|
|
3
6
|
const normalizeType = (type, value) => {
|
|
4
7
|
let normalizedValue = value
|
|
5
8
|
|
|
@@ -22,8 +25,12 @@ const normalizeType = (type, value) => {
|
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
if (isStringValue) {
|
|
25
|
-
const isTrue = value.toLowerCase()
|
|
26
|
-
|
|
28
|
+
const isTrue = BOOLEAN_STRING_TRUE_VALUES.includes(value.toLowerCase())
|
|
29
|
+
const isFalse = BOOLEAN_STRING_FALSE_VALUES.includes(value.toLowerCase())
|
|
30
|
+
|
|
31
|
+
if (isTrue || isFalse) {
|
|
32
|
+
normalizedValue = isTrue ? true : false
|
|
33
|
+
}
|
|
27
34
|
}
|
|
28
35
|
}
|
|
29
36
|
}
|