@kravc/schema 2.1.0 → 2.3.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/package.json +8 -8
- package/src/CredentialFactory.js +15 -7
- package/src/Schema.spec.js +2 -2
- package/src/Validator.js +18 -3
- package/src/Validator.spec.js +24 -2
- package/src/helpers/getReferenceIds.js +3 -9
- package/src/index.js +0 -1
- package/src/helpers/verifyReferences.js +0 -26
- package/src/helpers/verifyReferences.spec.js +0 -29
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kravc/schema",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Advanced JSON schema manipulation and validation library.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"JSON",
|
|
@@ -34,15 +34,15 @@
|
|
|
34
34
|
"lodash.pick": "^4.4.0",
|
|
35
35
|
"lodash.uniq": "^4.5.0",
|
|
36
36
|
"security-context": "^4.0.0",
|
|
37
|
-
"validator": "^
|
|
38
|
-
"z-schema": "^5.0.
|
|
37
|
+
"validator": "^13.7.0",
|
|
38
|
+
"z-schema": "^5.0.2"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"chai": "^4.
|
|
42
|
-
"eslint": "^
|
|
43
|
-
"js-yaml": "^
|
|
44
|
-
"jsonld": "^
|
|
45
|
-
"mocha": "^
|
|
41
|
+
"chai": "^4.3.4",
|
|
42
|
+
"eslint": "^8.6.0",
|
|
43
|
+
"js-yaml": "^4.1.0",
|
|
44
|
+
"jsonld": "^5.2.0",
|
|
45
|
+
"mocha": "^9.1.3",
|
|
46
46
|
"nyc": "^15.0.1"
|
|
47
47
|
},
|
|
48
48
|
"nyc": {
|
package/src/CredentialFactory.js
CHANGED
|
@@ -29,13 +29,24 @@ class CredentialFactory {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
get credentialType() {
|
|
33
|
+
const [ credentialType ] = this._uri.split('/').reverse()
|
|
34
|
+
|
|
35
|
+
return credentialType
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get context() {
|
|
39
|
+
return {
|
|
40
|
+
[this.credentialType]: { '@id': this._uri },
|
|
41
|
+
...this._context
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
32
45
|
createCredential(id, holder, subject = {}) {
|
|
33
46
|
validateId('id', id)
|
|
34
47
|
validateId('holder', holder)
|
|
35
48
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
const type = [ 'VerifiableCredential', credentialType ]
|
|
49
|
+
const type = [ 'VerifiableCredential', this.credentialType ]
|
|
39
50
|
|
|
40
51
|
const [ rootType ] = this._types
|
|
41
52
|
const credentialSubject = this._validator.validate(subject, rootType.id)
|
|
@@ -43,10 +54,7 @@ class CredentialFactory {
|
|
|
43
54
|
return {
|
|
44
55
|
'@context': [
|
|
45
56
|
CREDENTIALS_CONTEXT_V1_URL,
|
|
46
|
-
|
|
47
|
-
[credentialType]: { '@id': this._uri },
|
|
48
|
-
...this._context
|
|
49
|
-
}
|
|
57
|
+
this.context
|
|
50
58
|
],
|
|
51
59
|
id,
|
|
52
60
|
type,
|
package/src/Schema.spec.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { load } = require('js-yaml')
|
|
3
4
|
const { Schema } = require('src')
|
|
4
5
|
const { expect } = require('chai')
|
|
5
|
-
const { safeLoad } = require('js-yaml')
|
|
6
6
|
const { readFileSync } = require('fs')
|
|
7
7
|
|
|
8
8
|
const loadSync = (yamlPath) => {
|
|
9
9
|
const id = yamlPath.split('.')[0].split('/').reverse()[0]
|
|
10
|
-
const source =
|
|
10
|
+
const source = load(readFileSync(yamlPath))
|
|
11
11
|
|
|
12
12
|
return new Schema(source, id)
|
|
13
13
|
}
|
package/src/Validator.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const keyBy = require('lodash.keyby')
|
|
4
|
+
const groupBy = require('lodash.groupby')
|
|
4
5
|
const ZSchema = require('z-schema')
|
|
6
|
+
const getReferenceIds = require('./helpers/getReferenceIds')
|
|
5
7
|
const ValidationError = require('./ValidationError')
|
|
6
|
-
const verifyReferences = require('./helpers/verifyReferences')
|
|
7
8
|
const cleanupAttributes = require('./helpers/cleanupAttributes')
|
|
8
9
|
const normalizeAttributes = require('./helpers/normalizeAttributes')
|
|
9
10
|
|
|
@@ -13,6 +14,17 @@ class Validator {
|
|
|
13
14
|
throw new Error('No schemas provided')
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
const groupsById = groupBy(schemas, 'id')
|
|
18
|
+
|
|
19
|
+
for (const id in groupsById) {
|
|
20
|
+
const schemas = groupsById[id]
|
|
21
|
+
const hasDuplicates = schemas.length > 1
|
|
22
|
+
|
|
23
|
+
if (hasDuplicates) {
|
|
24
|
+
throw new Error(`Multiple "${id}" schemas provided`)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
16
28
|
this._engine = new ZSchema({ ignoreUnknownFormats: true })
|
|
17
29
|
|
|
18
30
|
const jsonSchemas = schemas.map(({ jsonSchema }) => jsonSchema)
|
|
@@ -23,8 +35,6 @@ class Validator {
|
|
|
23
35
|
throw new Error(`Schemas validation failed:\n${json}`)
|
|
24
36
|
}
|
|
25
37
|
|
|
26
|
-
verifyReferences(schemas)
|
|
27
|
-
|
|
28
38
|
this._schemasMap = keyBy(schemas, 'id')
|
|
29
39
|
this._jsonSchemasMap = keyBy(jsonSchemas, 'id')
|
|
30
40
|
}
|
|
@@ -66,6 +76,11 @@ class Validator {
|
|
|
66
76
|
get schemasMap() {
|
|
67
77
|
return this._schemasMap
|
|
68
78
|
}
|
|
79
|
+
|
|
80
|
+
getReferenceIds(schemaId) {
|
|
81
|
+
const schema = this._schemasMap[schemaId]
|
|
82
|
+
return getReferenceIds(schema, this._schemasMap)
|
|
83
|
+
}
|
|
69
84
|
}
|
|
70
85
|
|
|
71
86
|
module.exports = Validator
|
package/src/Validator.spec.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { load } = require('js-yaml')
|
|
3
4
|
const { expect } = require('chai')
|
|
4
|
-
const { safeLoad } = require('js-yaml')
|
|
5
5
|
const { readFileSync } = require('fs')
|
|
6
6
|
const { Schema, Validator } = require('src')
|
|
7
7
|
|
|
8
8
|
const loadSync = (yamlPath) => {
|
|
9
9
|
const id = yamlPath.split('.')[0].split('/').reverse()[0]
|
|
10
|
-
const source =
|
|
10
|
+
const source = load(readFileSync(yamlPath))
|
|
11
11
|
|
|
12
12
|
return new Schema(source, id)
|
|
13
13
|
}
|
|
@@ -174,6 +174,19 @@ describe('Validator', () => {
|
|
|
174
174
|
() => validator.validate({}, 'Account')
|
|
175
175
|
).to.throw('Schema "Account" not found')
|
|
176
176
|
})
|
|
177
|
+
|
|
178
|
+
it('throws error if multiple schemas with same id', async () => {
|
|
179
|
+
const exampleSchema1 = new Schema({
|
|
180
|
+
number: { required: true }
|
|
181
|
+
}, 'Example')
|
|
182
|
+
|
|
183
|
+
const exampleSchema2 = new Schema({
|
|
184
|
+
id: {}
|
|
185
|
+
}, 'Example')
|
|
186
|
+
|
|
187
|
+
expect(() => new Validator([ exampleSchema1, exampleSchema2 ]))
|
|
188
|
+
.to.throw('Multiple "Example" schemas provided')
|
|
189
|
+
})
|
|
177
190
|
})
|
|
178
191
|
|
|
179
192
|
describe('.normalize(object, schemaId)', () => {
|
|
@@ -204,4 +217,13 @@ describe('Validator', () => {
|
|
|
204
217
|
expect(validator.schemasMap).to.exist
|
|
205
218
|
})
|
|
206
219
|
})
|
|
220
|
+
|
|
221
|
+
describe('.getReferenceIds(schemaId)', () => {
|
|
222
|
+
it('returns ids of referenced schemas', () => {
|
|
223
|
+
const validator = new Validator(SCHEMAS)
|
|
224
|
+
const referenceIds = validator.getReferenceIds('Profile')
|
|
225
|
+
|
|
226
|
+
expect(referenceIds).to.eql([ 'Status', 'FavoriteItem', 'Preferences' ])
|
|
227
|
+
})
|
|
228
|
+
})
|
|
207
229
|
})
|
|
@@ -5,15 +5,9 @@ const Schema = require('../Schema')
|
|
|
5
5
|
const isUndefined = require('lodash.isundefined')
|
|
6
6
|
|
|
7
7
|
const getReferenceIds = (schema, schemasMap) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const getSchema = (id, referrerPath) => {
|
|
11
|
-
if (!schemasMap[id]) {
|
|
12
|
-
throw new Error(`Schema "${id}" not found, referenced by "${referrerPath}"`)
|
|
13
|
-
}
|
|
8
|
+
const getSchema = id => schemasMap[id]
|
|
14
9
|
|
|
15
|
-
|
|
16
|
-
}
|
|
10
|
+
let referenceIds = []
|
|
17
11
|
|
|
18
12
|
const { jsonSchema } = schema
|
|
19
13
|
const { id, enum: isEnum } = jsonSchema
|
|
@@ -67,7 +61,7 @@ const getReferenceIds = (schema, schemasMap) => {
|
|
|
67
61
|
const itemSchema = new Schema(itemProperties, `${id}.${propertyName}.items.properties`)
|
|
68
62
|
const itemReferenceIds = getReferenceIds(itemSchema, schemasMap)
|
|
69
63
|
|
|
70
|
-
referenceIds = [ ...referenceIds, itemReferenceIds ]
|
|
64
|
+
referenceIds = [ ...referenceIds, ...itemReferenceIds ]
|
|
71
65
|
continue
|
|
72
66
|
}
|
|
73
67
|
}
|
package/src/index.js
CHANGED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const keyBy = require('lodash.keyby')
|
|
4
|
-
const groupBy = require('lodash.groupby')
|
|
5
|
-
const getReferenceIds = require('./getReferenceIds')
|
|
6
|
-
|
|
7
|
-
const verifyReferences = schemas => {
|
|
8
|
-
const groupsById = groupBy(schemas, 'id')
|
|
9
|
-
|
|
10
|
-
for (const id in groupsById) {
|
|
11
|
-
const schemas = groupsById[id]
|
|
12
|
-
const hasDuplicates = schemas.length > 1
|
|
13
|
-
|
|
14
|
-
if (hasDuplicates) {
|
|
15
|
-
throw new Error(`Multiple "${id}" schemas defined`)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const schemasMap = keyBy(schemas, 'id')
|
|
20
|
-
|
|
21
|
-
for (const schema of schemas) {
|
|
22
|
-
getReferenceIds(schema, schemasMap)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
module.exports = verifyReferences
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const Schema = require('../Schema')
|
|
4
|
-
const { expect } = require('chai')
|
|
5
|
-
const verifyReferences = require('./verifyReferences')
|
|
6
|
-
|
|
7
|
-
describe('verifyReferences(schemas)', () => {
|
|
8
|
-
it('throws error if multiple schemas with same id', async () => {
|
|
9
|
-
const exampleSchema1 = new Schema({
|
|
10
|
-
number: { required: true }
|
|
11
|
-
}, 'Example')
|
|
12
|
-
|
|
13
|
-
const exampleSchema2 = new Schema({
|
|
14
|
-
id: {}
|
|
15
|
-
}, 'Example')
|
|
16
|
-
|
|
17
|
-
expect(() => verifyReferences([ exampleSchema1, exampleSchema2 ]))
|
|
18
|
-
.to.throw('Multiple "Example" schemas defined')
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('throws error if referenced schema not found', async () => {
|
|
22
|
-
const exampleSchema = new Schema({
|
|
23
|
-
document: { $ref: 'Document'}
|
|
24
|
-
}, 'Example')
|
|
25
|
-
|
|
26
|
-
expect(() => verifyReferences([ exampleSchema ]))
|
|
27
|
-
.to.throw('Schema "Document" not found, referenced by "Example.document.$ref"')
|
|
28
|
-
})
|
|
29
|
-
})
|