@@ -7,6 +7,7 @@ import { isObject } from "../utils/isObject";
7
7
import { validateNode } from "../validateNode" ;
8
8
import { get , split } from "@sagold/json-pointer" ;
9
9
import { mergeNode } from "../mergeNode" ;
10
+ import { pick } from "../utils/pick" ;
10
11
11
12
export const $refKeyword : Keyword = {
12
13
id : "$ref" ,
@@ -108,6 +109,7 @@ export function resolveRef({ pointer, path }: { pointer?: string; path?: Validat
108
109
if ( resolvedNode != null ) {
109
110
path ?. push ( { pointer, node : resolvedNode } ) ;
110
111
}
112
+
111
113
return resolvedNode ;
112
114
}
113
115
@@ -128,22 +130,22 @@ function resolveRecursiveRef(node: SchemaNode, path: ValidationPath): SchemaNode
128
130
const nonMatchingDynamicAnchor = node . context . dynamicAnchors [ refInCurrentScope ] == null ;
129
131
if ( nonMatchingDynamicAnchor ) {
130
132
if ( node . context . anchors [ refInCurrentScope ] ) {
131
- return compileNext ( node . context . anchors [ refInCurrentScope ] , node . evaluationPath ) ;
133
+ return compileNext ( node . context . anchors [ refInCurrentScope ] , node ) ;
132
134
}
133
135
}
134
136
135
137
for ( let i = 0 ; i < history . length ; i += 1 ) {
136
138
// A $dynamicRef that initially resolves to a schema with a matching $dynamicAnchor resolves to the first $dynamicAnchor in the dynamic scope
137
139
if ( history [ i ] . node . schema . $dynamicAnchor ) {
138
- return compileNext ( history [ i ] . node , node . evaluationPath ) ;
140
+ return compileNext ( history [ i ] . node , node ) ;
139
141
}
140
142
141
143
// A $dynamicRef only stops at a $dynamicAnchor if it is in the same dynamic scope.
142
144
const refWithoutScope = node . schema . $dynamicRef . split ( "#" ) . pop ( ) ;
143
145
const ref = joinId ( history [ i ] . node . $id , `#${ refWithoutScope } ` ) ;
144
146
const anchorNode = node . context . dynamicAnchors [ ref ] ;
145
147
if ( anchorNode ) {
146
- return compileNext ( node . context . dynamicAnchors [ ref ] , node . evaluationPath ) ;
148
+ return compileNext ( node . context . dynamicAnchors [ ref ] , node ) ;
147
149
}
148
150
}
149
151
@@ -153,12 +155,21 @@ function resolveRecursiveRef(node: SchemaNode, path: ValidationPath): SchemaNode
153
155
return nextNode ;
154
156
}
155
157
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" ] ;
160
159
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
+ ) ;
162
173
}
163
174
164
175
export function getRef ( node : SchemaNode , $ref = node ?. $ref ) : SchemaNode | undefined {
@@ -168,16 +179,16 @@ export function getRef(node: SchemaNode, $ref = node?.$ref): SchemaNode | undefi
168
179
169
180
// resolve $ref by json-evaluationPath
170
181
if ( node . context . refs [ $ref ] ) {
171
- return compileNext ( node . context . refs [ $ref ] , node . evaluationPath ) ;
182
+ return compileNext ( node . context . refs [ $ref ] , node ) ;
172
183
}
173
184
// resolve $ref from $anchor
174
185
if ( node . context . anchors [ $ref ] ) {
175
- return compileNext ( node . context . anchors [ $ref ] , node . evaluationPath ) ;
186
+ return compileNext ( node . context . anchors [ $ref ] , node ) ;
176
187
}
177
188
// resolve $ref from $dynamicAnchor
178
189
if ( node . context . dynamicAnchors [ $ref ] ) {
179
190
// 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 ) ;
181
192
}
182
193
183
194
// check for remote-host + pointer pair to switch rootSchema
@@ -191,7 +202,7 @@ export function getRef(node: SchemaNode, $ref = node?.$ref): SchemaNode | undefi
191
202
const $ref = fragments [ 0 ] ;
192
203
// this is a reference to remote-host root node
193
204
if ( node . context . remotes [ $ref ] ) {
194
- return compileNext ( node . context . remotes [ $ref ] , node . evaluationPath ) ;
205
+ return compileNext ( node . context . remotes [ $ref ] , node ) ;
195
206
}
196
207
if ( $ref [ 0 ] === "#" ) {
197
208
// support refOfUnknownKeyword
0 commit comments