Skip to content

Commit e2b6ef4

Browse files
fix: track schema dependecies (fastify#556)
1 parent 182a69b commit e2b6ef4

File tree

4 files changed

+57
-12
lines changed

4 files changed

+57
-12
lines changed

index.js

+6-7
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,7 @@ function resolveRef (location, ref) {
5656
throw new Error(`Cannot find reference "${ref}"`)
5757
}
5858

59-
if (location.isValidated) {
60-
validatorSchemasIds.add(schemaId)
61-
}
62-
63-
const newLocation = new Location(schema, schemaId, jsonPointer, location.isValidated)
59+
const newLocation = new Location(schema, schemaId, jsonPointer)
6460
if (schema.$ref !== undefined) {
6561
return resolveRef(newLocation, schema.$ref)
6662
}
@@ -137,6 +133,11 @@ function build (schema, options) {
137133
for (const schemaId of validatorSchemasIds) {
138134
const schema = refResolver.getSchema(schemaId)
139135
validator.addSchema(schema, schemaId)
136+
137+
const dependencies = refResolver.getSchemaDependencies(schemaId)
138+
for (const [schemaId, schema] of Object.entries(dependencies)) {
139+
validator.addSchema(schema, schemaId)
140+
}
140141
}
141142

142143
const dependenciesName = ['validator', 'serializer', contextFunctionCode]
@@ -454,7 +455,6 @@ function mergeAllOfSchema (location, schema, mergedSchema) {
454455
}
455456

456457
function addIfThenElse (location, input) {
457-
location.isValidated = true
458458
validatorSchemasIds.add(location.getSchemaId())
459459

460460
const schema = merge({}, location.schema)
@@ -840,7 +840,6 @@ function buildValue (location, input) {
840840
let code = ''
841841

842842
if (type === undefined && (schema.anyOf || schema.oneOf)) {
843-
location.isValidated = true
844843
validatorSchemasIds.add(location.getSchemaId())
845844

846845
const type = schema.anyOf ? 'anyOf' : 'oneOf'

lib/location.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
'use strict'
22

33
class Location {
4-
constructor (schema, schemaId, jsonPointer = '#', isValidated = false) {
4+
constructor (schema, schemaId, jsonPointer = '#') {
55
this.schema = schema
66
this.schemaId = schemaId
77
this.jsonPointer = jsonPointer
8-
this.isValidated = isValidated
98
this.mergedSchemaId = null
109
}
1110

1211
getPropertyLocation (propertyName) {
1312
const propertyLocation = new Location(
1413
this.schema[propertyName],
1514
this.schemaId,
16-
this.jsonPointer + '/' + propertyName,
17-
this.isValidated
15+
this.jsonPointer + '/' + propertyName
1816
)
1917

2018
if (this.mergedSchemaId !== null) {

lib/ref-resolver.js

+21-1
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,26 @@ class RefResolver {
2828
return getDataByJSONPointer(schema.schema, jsonPointer)
2929
}
3030

31+
getSchemaDependencies (schemaId, dependencies = {}) {
32+
const schema = this.schemas[schemaId]
33+
34+
for (const dependencySchemaId of schema.dependencies) {
35+
if (dependencies[dependencySchemaId] !== undefined) continue
36+
dependencies[dependencySchemaId] = this.getSchema(dependencySchemaId)
37+
this.getSchemaDependencies(dependencySchemaId, dependencies)
38+
}
39+
40+
return dependencies
41+
}
42+
3143
insertSchemaBySchemaId (schema, schemaId) {
3244
if (
3345
this.schemas[schemaId] !== undefined &&
3446
!deepEqual(schema, this.schemas[schemaId].schema)
3547
) {
3648
throw new Error(`There is already another schema with id ${schemaId}`)
3749
}
38-
this.schemas[schemaId] = { schema, anchors: {} }
50+
this.schemas[schemaId] = { schema, anchors: {}, dependencies: [] }
3951
}
4052

4153
insertSchemaByAnchor (schema, schemaId, anchor) {
@@ -60,6 +72,14 @@ class RefResolver {
6072
}
6173
}
6274

75+
const ref = schema.$ref
76+
if (ref !== undefined && typeof ref === 'string') {
77+
if (ref.charAt(0) !== '#') {
78+
const dependencySchemaId = ref.split('#')[0]
79+
this.schemas[rootSchemaId].dependencies.push(dependencySchemaId)
80+
}
81+
}
82+
6383
for (const key in schema) {
6484
if (typeof schema[key] === 'object' && schema[key] !== null) {
6585
this.insertSchemaSubschemas(schema[key], rootSchemaId)

test/anyof.test.js

+28
Original file line numberDiff line numberDiff line change
@@ -616,3 +616,31 @@ test('anyOf with a nested external schema', (t) => {
616616
const stringify = build(schema, { schema: externalSchemas })
617617
t.equal(stringify('foo'), '"foo"')
618618
})
619+
620+
test('object with ref and validated properties', (t) => {
621+
t.plan(1)
622+
623+
const externalSchemas = {
624+
RefSchema: {
625+
$id: 'RefSchema',
626+
type: 'string'
627+
}
628+
}
629+
630+
const schema = {
631+
$id: 'root',
632+
type: 'object',
633+
properties: {
634+
id: {
635+
anyOf: [
636+
{ type: 'string' },
637+
{ type: 'number' }
638+
]
639+
},
640+
reference: { $ref: 'RefSchema' }
641+
}
642+
}
643+
644+
const stringify = build(schema, { schema: externalSchemas })
645+
t.equal(stringify({ id: 1, reference: 'hi' }), '{"id":1,"reference":"hi"}')
646+
})

0 commit comments

Comments
 (0)