@@ -5,6 +5,7 @@ import { isObject } from "../utils/isObject";
5
5
import { validateNode } from "../validateNode" ;
6
6
import { get , split } from "@sagold/json-pointer" ;
7
7
import { mergeNode } from "../mergeNode" ;
8
+ import { pick } from "../utils/pick" ;
8
9
export const $refKeyword = {
9
10
id : "$ref" ,
10
11
keyword : "$ref" ,
@@ -109,48 +110,53 @@ function resolveRecursiveRef(node, path) {
109
110
const nonMatchingDynamicAnchor = node . context . dynamicAnchors [ refInCurrentScope ] == null ;
110
111
if ( nonMatchingDynamicAnchor ) {
111
112
if ( node . context . anchors [ refInCurrentScope ] ) {
112
- return compileNext ( node . context . anchors [ refInCurrentScope ] , node . evaluationPath ) ;
113
+ return compileNext ( node . context . anchors [ refInCurrentScope ] , node ) ;
113
114
}
114
115
}
115
116
for ( let i = 0 ; i < history . length ; i += 1 ) {
116
117
// A $dynamicRef that initially resolves to a schema with a matching $dynamicAnchor resolves to the first $dynamicAnchor in the dynamic scope
117
118
if ( history [ i ] . node . schema . $dynamicAnchor ) {
118
- return compileNext ( history [ i ] . node , node . evaluationPath ) ;
119
+ return compileNext ( history [ i ] . node , node ) ;
119
120
}
120
121
// A $dynamicRef only stops at a $dynamicAnchor if it is in the same dynamic scope.
121
122
const refWithoutScope = node . schema . $dynamicRef . split ( "#" ) . pop ( ) ;
122
123
const ref = joinId ( history [ i ] . node . $id , `#${ refWithoutScope } ` ) ;
123
124
const anchorNode = node . context . dynamicAnchors [ ref ] ;
124
125
if ( anchorNode ) {
125
- return compileNext ( node . context . dynamicAnchors [ ref ] , node . evaluationPath ) ;
126
+ return compileNext ( node . context . dynamicAnchors [ ref ] , node ) ;
126
127
}
127
128
}
128
129
// A $dynamicRef without a matching $dynamicAnchor in the same schema resource behaves like a normal $ref to $anchor
129
130
const nextNode = getRef ( node , refInCurrentScope ) ;
130
131
return nextNode ;
131
132
}
132
- function compileNext ( referencedNode , evaluationPath = referencedNode . evaluationPath ) {
133
- const referencedSchema = isObject ( referencedNode . schema )
134
- ? omit ( referencedNode . schema , "$id" )
135
- : referencedNode . schema ;
136
- return referencedNode . compileSchema ( referencedSchema , `${ evaluationPath } /$ref` , referencedNode . schemaLocation ) ;
133
+ const PROPERTIES_TO_MERGE = [ "title" , "description" , "options" , "readOnly" , "writeOnly" ] ;
134
+ function compileNext ( referencedNode , sourceNode ) {
135
+ let referencedSchema = referencedNode . schema ;
136
+ if ( isObject ( referencedNode . schema ) ) {
137
+ referencedSchema = {
138
+ ...omit ( referencedNode . schema , "$id" ) ,
139
+ ...pick ( sourceNode . schema , ...PROPERTIES_TO_MERGE )
140
+ } ;
141
+ }
142
+ return referencedNode . compileSchema ( referencedSchema , `${ sourceNode . evaluationPath } /$ref` , referencedNode . schemaLocation ) ;
137
143
}
138
144
export function getRef ( node , $ref = node === null || node === void 0 ? void 0 : node . $ref ) {
139
145
if ( $ref == null ) {
140
146
return node ;
141
147
}
142
148
// resolve $ref by json-evaluationPath
143
149
if ( node . context . refs [ $ref ] ) {
144
- return compileNext ( node . context . refs [ $ref ] , node . evaluationPath ) ;
150
+ return compileNext ( node . context . refs [ $ref ] , node ) ;
145
151
}
146
152
// resolve $ref from $anchor
147
153
if ( node . context . anchors [ $ref ] ) {
148
- return compileNext ( node . context . anchors [ $ref ] , node . evaluationPath ) ;
154
+ return compileNext ( node . context . anchors [ $ref ] , node ) ;
149
155
}
150
156
// resolve $ref from $dynamicAnchor
151
157
if ( node . context . dynamicAnchors [ $ref ] ) {
152
158
// A $ref to a $dynamicAnchor in the same schema resource behaves like a normal $ref to an $anchor
153
- return compileNext ( node . context . dynamicAnchors [ $ref ] , node . evaluationPath ) ;
159
+ return compileNext ( node . context . dynamicAnchors [ $ref ] , node ) ;
154
160
}
155
161
// check for remote-host + pointer pair to switch rootSchema
156
162
const fragments = splitRef ( $ref ) ;
@@ -162,7 +168,7 @@ export function getRef(node, $ref = node === null || node === void 0 ? void 0 :
162
168
const $ref = fragments [ 0 ] ;
163
169
// this is a reference to remote-host root node
164
170
if ( node . context . remotes [ $ref ] ) {
165
- return compileNext ( node . context . remotes [ $ref ] , node . evaluationPath ) ;
171
+ return compileNext ( node . context . remotes [ $ref ] , node ) ;
166
172
}
167
173
if ( $ref [ 0 ] === "#" ) {
168
174
// support refOfUnknownKeyword
0 commit comments