11'use strict'
22
3+ const deepEqual = require ( 'fast-deep-equal' )
4+
35class RefResolver {
46 constructor ( ) {
5- this . refs = { }
7+ this . schemas = { }
68 }
79
810 addSchema ( schema , schemaKey ) {
9- if ( schema === null ) return
10-
1111 if ( schema . $id !== undefined && schema . $id . charAt ( 0 ) !== '#' ) {
1212 schemaKey = schema . $id
1313 }
14-
15- this . refs [ schemaKey ] = { schema, anchors : { } }
16- this . resolveSchema ( schema , schemaKey , '' )
14+ this . insertSchemaBySchemaId ( schema , schemaKey )
15+ this . insertSchemaSubschemas ( schema , schemaKey )
1716 }
1817
1918 getSchema ( schemaReference ) {
2019 const [ schemaKey , jsonPointer ] = schemaReference . split ( '#' )
21- const schema = this . refs [ schemaKey ]
22-
20+ const schema = this . schemas [ schemaKey ]
2321 if ( schema === undefined ) {
2422 return undefined
2523 }
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+ }
2639
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
2849 }
2950
30- resolveSchema ( schema , schemaKey , jsonPointer ) {
51+ insertSchemaSubschemas ( schema , rootSchemaId ) {
3152 const schemaId = schema . $id
3253 if ( schemaId !== undefined && typeof schemaId === 'string' ) {
3354 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 )
3557 } else {
36- this . refs [ schemaId ] = { schema, anchors : { } }
58+ this . insertSchemaBySchemaId ( schema , schemaId )
3759 }
3860 }
3961
4062 for ( const key in schema ) {
4163 if ( typeof schema [ key ] === 'object' && schema [ key ] !== null ) {
42- this . resolveSchema ( schema [ key ] , schemaKey , jsonPointer + '/' + key )
64+ this . insertSchemaSubschemas ( schema [ key ] , rootSchemaId )
4365 }
4466 }
4567 }
@@ -48,15 +70,9 @@ class RefResolver {
4870function getDataByJSONPointer ( data , jsonPointer ) {
4971 const parts = jsonPointer . split ( '/' )
5072 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 ) {
6076 return undefined
6177 }
6278 current = current [ part ]
0 commit comments