@@ -7,6 +7,7 @@ import { isObject } from "../utils/isObject";
77import { validateNode } from "../validateNode" ;
88import { get , split } from "@sagold/json-pointer" ;
99import { mergeNode } from "../mergeNode" ;
10+ import { pick } from "../utils/pick" ;
1011
1112export const $refKeyword : Keyword = {
1213 id : "$ref" ,
@@ -108,6 +109,7 @@ export function resolveRef({ pointer, path }: { pointer?: string; path?: Validat
108109 if ( resolvedNode != null ) {
109110 path ?. push ( { pointer, node : resolvedNode } ) ;
110111 }
112+
111113 return resolvedNode ;
112114}
113115
@@ -128,22 +130,22 @@ function resolveRecursiveRef(node: SchemaNode, path: ValidationPath): SchemaNode
128130 const nonMatchingDynamicAnchor = node . context . dynamicAnchors [ refInCurrentScope ] == null ;
129131 if ( nonMatchingDynamicAnchor ) {
130132 if ( node . context . anchors [ refInCurrentScope ] ) {
131- return compileNext ( node . context . anchors [ refInCurrentScope ] , node . evaluationPath ) ;
133+ return compileNext ( node . context . anchors [ refInCurrentScope ] , node ) ;
132134 }
133135 }
134136
135137 for ( let i = 0 ; i < history . length ; i += 1 ) {
136138 // A $dynamicRef that initially resolves to a schema with a matching $dynamicAnchor resolves to the first $dynamicAnchor in the dynamic scope
137139 if ( history [ i ] . node . schema . $dynamicAnchor ) {
138- return compileNext ( history [ i ] . node , node . evaluationPath ) ;
140+ return compileNext ( history [ i ] . node , node ) ;
139141 }
140142
141143 // A $dynamicRef only stops at a $dynamicAnchor if it is in the same dynamic scope.
142144 const refWithoutScope = node . schema . $dynamicRef . split ( "#" ) . pop ( ) ;
143145 const ref = joinId ( history [ i ] . node . $id , `#${ refWithoutScope } ` ) ;
144146 const anchorNode = node . context . dynamicAnchors [ ref ] ;
145147 if ( anchorNode ) {
146- return compileNext ( node . context . dynamicAnchors [ ref ] , node . evaluationPath ) ;
148+ return compileNext ( node . context . dynamicAnchors [ ref ] , node ) ;
147149 }
148150 }
149151
@@ -153,12 +155,21 @@ function resolveRecursiveRef(node: SchemaNode, path: ValidationPath): SchemaNode
153155 return nextNode ;
154156}
155157
156- function compileNext ( referencedNode : SchemaNode , evaluationPath = referencedNode . evaluationPath ) {
157- const referencedSchema = isObject ( referencedNode . schema )
158- ? omit ( referencedNode . schema , "$id" )
159- : referencedNode . schema ;
158+ const PROPERTIES_TO_MERGE = [ "title" , "description" , "options" , "readOnly" , "writeOnly" ] ;
160159
161- return referencedNode . compileSchema ( referencedSchema , `${ evaluationPath } /$ref` , referencedNode . schemaLocation ) ;
160+ function compileNext ( referencedNode : SchemaNode , sourceNode : SchemaNode ) {
161+ let referencedSchema = referencedNode . schema ;
162+ if ( isObject ( referencedNode . schema ) ) {
163+ referencedSchema = {
164+ ...omit ( referencedNode . schema , "$id" ) ,
165+ ...pick ( sourceNode . schema , ...PROPERTIES_TO_MERGE )
166+ } ;
167+ }
168+ return referencedNode . compileSchema (
169+ referencedSchema ,
170+ `${ sourceNode . evaluationPath } /$ref` ,
171+ referencedNode . schemaLocation
172+ ) ;
162173}
163174
164175export function getRef ( node : SchemaNode , $ref = node ?. $ref ) : SchemaNode | undefined {
@@ -168,16 +179,16 @@ export function getRef(node: SchemaNode, $ref = node?.$ref): SchemaNode | undefi
168179
169180 // resolve $ref by json-evaluationPath
170181 if ( node . context . refs [ $ref ] ) {
171- return compileNext ( node . context . refs [ $ref ] , node . evaluationPath ) ;
182+ return compileNext ( node . context . refs [ $ref ] , node ) ;
172183 }
173184 // resolve $ref from $anchor
174185 if ( node . context . anchors [ $ref ] ) {
175- return compileNext ( node . context . anchors [ $ref ] , node . evaluationPath ) ;
186+ return compileNext ( node . context . anchors [ $ref ] , node ) ;
176187 }
177188 // resolve $ref from $dynamicAnchor
178189 if ( node . context . dynamicAnchors [ $ref ] ) {
179190 // A $ref to a $dynamicAnchor in the same schema resource behaves like a normal $ref to an $anchor
180- return compileNext ( node . context . dynamicAnchors [ $ref ] , node . evaluationPath ) ;
191+ return compileNext ( node . context . dynamicAnchors [ $ref ] , node ) ;
181192 }
182193
183194 // check for remote-host + pointer pair to switch rootSchema
@@ -191,7 +202,7 @@ export function getRef(node: SchemaNode, $ref = node?.$ref): SchemaNode | undefi
191202 const $ref = fragments [ 0 ] ;
192203 // this is a reference to remote-host root node
193204 if ( node . context . remotes [ $ref ] ) {
194- return compileNext ( node . context . remotes [ $ref ] , node . evaluationPath ) ;
205+ return compileNext ( node . context . remotes [ $ref ] , node ) ;
195206 }
196207 if ( $ref [ 0 ] === "#" ) {
197208 // support refOfUnknownKeyword
0 commit comments