@@ -15,35 +15,6 @@ const ajv = new Ajv({
1515} )
1616addFormats ( ajv )
1717
18- // Proxy to resolve $refs in schema definitions
19- const Dereference = {
20- get ( target , property ) {
21- const value = target [ property ]
22-
23- if ( Array . isArray ( value ) ) {
24- // Schema definition returns an array for this property, return the array with all refs resolved
25- return value . map ( ( item , i ) => {
26- const $ref = item . $ref || this . join ( target . $id , `${ property } /${ i } ` )
27- return Schema . resolve ( $ref , target . $id )
28- } )
29- } else if ( value !== null && typeof value === 'object' ) {
30- // Schema definition returns an object for this property, return the subschema and proxy it
31- return Schema . proxy ( this . join ( target . $id , property ) , value )
32- } else if ( value !== undefined ) {
33- // Schema definition returns a value for this property, just return it
34- return value
35- } else if ( target . $ref ) {
36- // Schema includes a ref, so delegate to it
37- return Schema . resolve ( target . $ref , target . $id ) [ property ]
38- }
39- } ,
40-
41- join ( $id , path ) {
42- const url = new URL ( $id )
43- url . hash = [ url . hash , path ] . join ( '/' )
44- return url . toString ( )
45- }
46- }
4718
4819// Delegate property access to the schema definition
4920const DelegateToDefinition = {
@@ -62,7 +33,12 @@ export class Schema {
6233 const { href } = new URL ( $ref , $id )
6334 const validator = ajv . getSchema ( href )
6435
65- if ( ! validator ) throw new TypeError ( 'Schema not found: ' + href )
36+ if ( validator === undefined ) throw new TypeError ( 'Schema not found: ' + href )
37+
38+ // Schema definition is a primitive, just return it
39+ if ( typeof validator . schema !== 'object' ) return validator . schema
40+
41+ // Create a new proxy to the schema definition
6642 if ( ! validator . proxy ) validator . proxy = Schema . proxy ( href , validator . schema )
6743
6844 return validator . proxy
@@ -73,10 +49,11 @@ export class Schema {
7349 }
7450
7551 constructor ( $id , definition ) {
76- this . definition = new Proxy ( { $id, ...definition } , Dereference )
52+ this . $id = $id
53+ this . definition = new Proxy ( definition , this )
7754 }
7855
79- resolve ( $ref = this . definition . $ref , $id = this . definition . $id ) {
56+ resolve ( $ref = this . definition . $ref , $id = this . $id ) {
8057 return Schema . resolve ( $ref , $id )
8158 }
8259
@@ -90,11 +67,42 @@ export class Schema {
9067 }
9168
9269 validate ( data ) {
93- const validator = ajv . getSchema ( this . definition . $id )
70+ const validator = ajv . getSchema ( this . $id )
9471 const valid = validator ( data )
9572 const errors = validator . errors
9673 return { valid, errors }
9774 }
75+
76+ // This instance acts as a Proxy to resolve $refs in the schema definition
77+ get ( target , property ) {
78+ const value = target [ property ]
79+
80+ if ( Array . isArray ( value ) ) {
81+ // Schema definition returns an array for this property, return the array with all refs resolved
82+ return value . map ( ( item , i ) => {
83+ if ( typeof item === 'object' ) {
84+ return Schema . resolve ( item . $ref || this . join ( `${ property } /${ i } ` ) , this . $id )
85+ } else {
86+ return item
87+ }
88+ } )
89+ } else if ( value !== null && typeof value === 'object' ) {
90+ // Schema definition returns an object for this property, return the subschema and proxy it
91+ return Schema . proxy ( this . join ( property ) , value )
92+ } else if ( value !== undefined ) {
93+ // Schema definition returns a value for this property, just return it
94+ return value
95+ } else if ( target . $ref ) {
96+ // Schema includes a ref, so delegate to it
97+ return Schema . resolve ( target . $ref , this . $id ) [ property ]
98+ }
99+ }
100+
101+ join ( path , $id = this . $id ) {
102+ const url = new URL ( $id )
103+ url . hash = [ url . hash , path ] . join ( '/' )
104+ return url . toString ( )
105+ }
98106}
99107
100108export const schema = Schema . resolve ( '#' )
0 commit comments