1
1
'use strict'
2
2
3
+ const deepEqual = require ( 'fast-deep-equal' )
4
+
3
5
class RefResolver {
4
6
constructor ( ) {
5
- this . refs = { }
7
+ this . schemas = { }
6
8
}
7
9
8
10
addSchema ( schema , schemaKey ) {
9
- if ( schema === null ) return
10
-
11
11
if ( schema . $id !== undefined && schema . $id . charAt ( 0 ) !== '#' ) {
12
12
schemaKey = schema . $id
13
13
}
14
-
15
- this . refs [ schemaKey ] = { schema, anchors : { } }
16
- this . resolveSchema ( schema , schemaKey , '' )
14
+ this . insertSchemaBySchemaId ( schema , schemaKey )
15
+ this . insertSchemaSubschemas ( schema , schemaKey )
17
16
}
18
17
19
18
getSchema ( schemaReference ) {
20
19
const [ schemaKey , jsonPointer ] = schemaReference . split ( '#' )
21
- const schema = this . refs [ schemaKey ]
22
-
20
+ const schema = this . schemas [ schemaKey ]
23
21
if ( schema === undefined ) {
24
22
return undefined
25
23
}
24
+ if ( schema . anchors [ jsonPointer ] !== undefined ) {
25
+ return schema . anchors [ jsonPointer ]
26
+ }
27
+ return getDataByJSONPointer ( schema . schema , jsonPointer )
28
+ }
29
+
30
+ insertSchemaBySchemaId ( schema , schemaId ) {
31
+ if (
32
+ this . schemas [ schemaId ] !== undefined &&
33
+ ! deepEqual ( schema , this . schemas [ schemaId ] . schema )
34
+ ) {
35
+ throw new Error ( `There is already another schema with id ${ schemaId } ` )
36
+ }
37
+ this . schemas [ schemaId ] = { schema, anchors : { } }
38
+ }
26
39
27
- return schema . anchors [ jsonPointer ] || getDataByJSONPointer ( schema . schema , jsonPointer )
40
+ insertSchemaByAnchor ( schema , schemaId , anchor ) {
41
+ const { anchors } = this . schemas [ schemaId ]
42
+ if (
43
+ anchors [ anchor ] !== undefined &&
44
+ ! deepEqual ( schema , anchors [ anchor ] )
45
+ ) {
46
+ throw new Error ( `There is already another schema with id ${ schemaId } #${ anchor } ` )
47
+ }
48
+ anchors [ anchor ] = schema
28
49
}
29
50
30
- resolveSchema ( schema , schemaKey , jsonPointer ) {
51
+ insertSchemaSubschemas ( schema , rootSchemaId ) {
31
52
const schemaId = schema . $id
32
53
if ( schemaId !== undefined && typeof schemaId === 'string' ) {
33
54
if ( schemaId . charAt ( 0 ) === '#' ) {
34
- this . refs [ schemaKey ] . anchors [ schemaId . slice ( 1 ) ] = schema
55
+ const anchor = schemaId . slice ( 1 )
56
+ this . insertSchemaByAnchor ( schema , rootSchemaId , anchor )
35
57
} else {
36
- this . refs [ schemaId ] = { schema, anchors : { } }
58
+ this . insertSchemaBySchemaId ( schema , schemaId )
37
59
}
38
60
}
39
61
40
62
for ( const key in schema ) {
41
63
if ( typeof schema [ key ] === 'object' && schema [ key ] !== null ) {
42
- this . resolveSchema ( schema [ key ] , schemaKey , jsonPointer + '/' + key )
64
+ this . insertSchemaSubschemas ( schema [ key ] , rootSchemaId )
43
65
}
44
66
}
45
67
}
@@ -48,15 +70,9 @@ class RefResolver {
48
70
function getDataByJSONPointer ( data , jsonPointer ) {
49
71
const parts = jsonPointer . split ( '/' )
50
72
let current = data
51
- for ( let i = 0 ; i < parts . length ; i ++ ) {
52
- const part = parts [ i ]
53
- if ( part === '' ) {
54
- continue
55
- }
56
- if ( part . charAt ( 0 ) === '#' ) {
57
- continue
58
- }
59
- if ( current [ part ] === undefined ) {
73
+ for ( const part of parts ) {
74
+ if ( part === '' ) continue
75
+ if ( typeof current !== 'object' || current === null ) {
60
76
return undefined
61
77
}
62
78
current = current [ part ]
0 commit comments