1
1
import { SchemaNode } from "../types" ;
2
- import { Keyword , JsonSchemaValidatorParams , ValidationPath } from "../Keyword" ;
2
+ import { Keyword , JsonSchemaValidatorParams , ValidationPath , JsonSchemaReducerParams } from "../Keyword" ;
3
3
import { joinId } from "../utils/joinId" ;
4
4
import splitRef from "../utils/splitRef" ;
5
5
import { omit } from "../utils/omit" ;
6
6
import { isObject } from "../utils/isObject" ;
7
7
import { validateNode } from "../validateNode" ;
8
8
import { get , split } from "@sagold/json-pointer" ;
9
+ import { mergeNode } from "../mergeNode" ;
9
10
10
11
export const $refKeyword : Keyword = {
11
12
id : "$ref" ,
12
13
keyword : "$ref" ,
14
+ order : 10 ,
13
15
parse : parseRef ,
16
+ addReduce : ( node ) => node . $ref != null || node . schema . $dynamicRef != null ,
17
+ reduce : reduceRef ,
14
18
addValidate : ( { schema } ) => schema . $ref != null || schema . $dynamicRef != null ,
15
19
validate : validateRef
16
20
} ;
@@ -69,11 +73,21 @@ export function parseRef(node: SchemaNode) {
69
73
}
70
74
}
71
75
76
+ export function reduceRef ( { node, data, key, pointer, path } : JsonSchemaReducerParams ) {
77
+ const resolvedNode = node . resolveRef ( { pointer, path } ) ;
78
+ if ( resolvedNode . schemaId === node . schemaId ) {
79
+ return resolvedNode ;
80
+ }
81
+ const merged = mergeNode ( node , resolvedNode ) ;
82
+ const { node : reducedNode , error } = merged . reduceSchema ( data , { key, pointer, path } ) ;
83
+ return reducedNode ?? error ;
84
+ }
85
+
72
86
export function resolveRef ( { pointer, path } : { pointer ?: string ; path ?: ValidationPath } = { } ) {
73
87
const node = this as SchemaNode ;
88
+
74
89
if ( node . schema . $dynamicRef ) {
75
90
const nextNode = resolveRecursiveRef ( node , path ) ;
76
- // console.log("resolved node", node.schema.$dynamicRef, "=>", nextNode != null);
77
91
path ?. push ( { pointer, node : nextNode } ) ;
78
92
return nextNode ;
79
93
}
@@ -85,8 +99,6 @@ export function resolveRef({ pointer, path }: { pointer?: string; path?: Validat
85
99
const resolvedNode = getRef ( node ) ;
86
100
if ( resolvedNode != null ) {
87
101
path ?. push ( { pointer, node : resolvedNode } ) ;
88
- } else {
89
- // console.log("failed resolving", node.$ref, "from", Object.keys(node.context.refs));
90
102
}
91
103
return resolvedNode ;
92
104
}
@@ -103,9 +115,6 @@ function validateRef({ node, data, pointer = "#", path }: JsonSchemaValidatorPar
103
115
function resolveRecursiveRef ( node : SchemaNode , path : ValidationPath ) : SchemaNode {
104
116
const history = path ;
105
117
const refInCurrentScope = joinId ( node . $id , node . schema . $dynamicRef ) ;
106
- // console.log("resolve $dynamicRef:", node.schema.$dynamicRef);
107
- // console.log(" -> scope:", joinId(node.$id, node.schema.$dynamicRef));
108
- // console.log("dynamicAnchors", Object.keys(node.context.dynamicAnchors));
109
118
110
119
// A $dynamicRef with a non-matching $dynamicAnchor in the same schema resource behaves like a normal $ref to $anchor
111
120
const nonMatchingDynamicAnchor = node . context . dynamicAnchors [ refInCurrentScope ] == null ;
@@ -131,7 +140,7 @@ function resolveRecursiveRef(node: SchemaNode, path: ValidationPath): SchemaNode
131
140
}
132
141
133
142
// A $dynamicRef without a matching $dynamicAnchor in the same schema resource behaves like a normal $ref to $anchor
134
- // console.log(" -> resolve as ref");
143
+
135
144
const nextNode = getRef ( node , refInCurrentScope ) ;
136
145
return nextNode ;
137
146
}
0 commit comments