Skip to content

Commit 5fb7be5

Browse files
fix: deref schema without root (#6)
1 parent f936bed commit 5fb7be5

File tree

2 files changed

+102
-38
lines changed

2 files changed

+102
-38
lines changed

Diff for: index.js

+51-38
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,41 @@ class RefResolver {
1919
this.#cloneSchemaWithoutRefs = opts.cloneSchemaWithoutRefs ?? false
2020
}
2121

22-
addSchema (schema, schemaId) {
23-
if (schema.$id !== undefined && schema.$id.charAt(0) !== '#') {
24-
// Schema has an $id that is not an anchor
25-
schemaId = schema.$id
26-
} else {
27-
// Schema has no $id or $id is an anchor
28-
this.#insertSchemaBySchemaId(schema, schemaId)
22+
addSchema (schema, rootSchemaId, isRootSchema = true) {
23+
if (isRootSchema) {
24+
if (schema.$id !== undefined && schema.$id.charAt(0) !== '#') {
25+
// Schema has an $id that is not an anchor
26+
rootSchemaId = schema.$id
27+
} else {
28+
// Schema has no $id or $id is an anchor
29+
this.#insertSchemaBySchemaId(schema, rootSchemaId)
30+
}
31+
}
32+
33+
const schemaId = schema.$id
34+
if (schemaId !== undefined && typeof schemaId === 'string') {
35+
if (schemaId.charAt(0) === '#') {
36+
this.#insertSchemaByAnchor(schema, rootSchemaId, schemaId)
37+
} else {
38+
this.#insertSchemaBySchemaId(schema, schemaId)
39+
rootSchemaId = schemaId
40+
}
41+
}
42+
43+
const ref = schema.$ref
44+
if (ref !== undefined && typeof ref === 'string') {
45+
const { refSchemaId, refJsonPointer } = this.#parseSchemaRef(ref, rootSchemaId)
46+
this.#schemas[rootSchemaId].refs.push({
47+
schemaId: refSchemaId,
48+
jsonPointer: refJsonPointer
49+
})
50+
}
51+
52+
for (const key in schema) {
53+
if (typeof schema[key] === 'object' && schema[key] !== null) {
54+
this.addSchema(schema[key], rootSchemaId, false)
55+
}
2956
}
30-
this.#addSchema(schema, schemaId)
3157
}
3258

3359
getSchema (schemaId, jsonPointer = '#') {
@@ -60,7 +86,11 @@ class RefResolver {
6086

6187
for (const ref of schema.refs) {
6288
const dependencySchemaId = ref.schemaId
63-
if (dependencies[dependencySchemaId] !== undefined) continue
89+
if (
90+
dependencySchemaId === schemaId ||
91+
dependencies[dependencySchemaId] !== undefined
92+
) continue
93+
6494
dependencies[dependencySchemaId] = this.getSchema(dependencySchemaId)
6595
this.getSchemaDependencies(dependencySchemaId, dependencies)
6696
}
@@ -84,12 +114,12 @@ class RefResolver {
84114
}
85115

86116
const refs = []
87-
this.#addDerefSchema(schema.schema, schemaId, refs)
117+
this.#addDerefSchema(schema.schema, schemaId, true, refs)
88118

89119
const dependencies = this.getSchemaDependencies(schemaId)
90120
for (const schemaId in dependencies) {
91121
const schema = dependencies[schemaId]
92-
this.#addDerefSchema(schema, schemaId, refs)
122+
this.#addDerefSchema(schema, schemaId, true, refs)
93123
}
94124

95125
for (const ref of refs) {
@@ -140,35 +170,18 @@ class RefResolver {
140170
}
141171
}
142172

143-
#addSchema (schema, rootSchemaId) {
144-
const schemaId = schema.$id
145-
if (schemaId !== undefined && typeof schemaId === 'string') {
146-
if (schemaId.charAt(0) === '#') {
147-
this.#insertSchemaByAnchor(schema, rootSchemaId, schemaId)
148-
} else {
149-
this.#insertSchemaBySchemaId(schema, schemaId)
150-
rootSchemaId = schemaId
151-
}
152-
}
153-
154-
const ref = schema.$ref
155-
if (ref !== undefined && typeof ref === 'string') {
156-
const { refSchemaId, refJsonPointer } = this.#parseSchemaRef(ref, rootSchemaId)
157-
this.#schemas[rootSchemaId].refs.push({
158-
schemaId: refSchemaId,
159-
jsonPointer: refJsonPointer
160-
})
161-
}
173+
#addDerefSchema (schema, rootSchemaId, isRootSchema, refs = []) {
174+
const derefSchema = Array.isArray(schema) ? [...schema] : { ...schema }
162175

163-
for (const key in schema) {
164-
if (typeof schema[key] === 'object' && schema[key] !== null) {
165-
this.#addSchema(schema[key], rootSchemaId)
176+
if (isRootSchema) {
177+
if (schema.$id !== undefined && schema.$id.charAt(0) !== '#') {
178+
// Schema has an $id that is not an anchor
179+
rootSchemaId = schema.$id
180+
} else {
181+
// Schema has no $id or $id is an anchor
182+
this.#insertDerefSchemaBySchemaId(derefSchema, rootSchemaId)
166183
}
167184
}
168-
}
169-
170-
#addDerefSchema (schema, rootSchemaId, refs = []) {
171-
const derefSchema = Array.isArray(schema) ? [...schema] : { ...schema }
172185

173186
const schemaId = derefSchema.$id
174187
if (schemaId !== undefined && typeof schemaId === 'string') {
@@ -191,7 +204,7 @@ class RefResolver {
191204
for (const key in derefSchema) {
192205
const value = derefSchema[key]
193206
if (typeof value === 'object' && value !== null) {
194-
derefSchema[key] = this.#addDerefSchema(value, rootSchemaId, refs)
207+
derefSchema[key] = this.#addDerefSchema(value, rootSchemaId, false, refs)
195208
}
196209
}
197210

Diff for: test/deref-schema.test.js

+51
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,54 @@ test('should throw if target ref schema is not found', () => {
234234
)
235235
}
236236
})
237+
238+
test('should deref schema without root $id', () => {
239+
const refResolver = new RefResolver()
240+
241+
const schemaId = 'schemaId1'
242+
const schema = {
243+
type: 'object',
244+
definitions: {
245+
id1: {
246+
type: 'object',
247+
properties: {
248+
id1: {
249+
type: 'integer'
250+
}
251+
}
252+
}
253+
},
254+
allOf: [
255+
{
256+
$ref: '#/definitions/id1'
257+
}
258+
]
259+
}
260+
261+
refResolver.addSchema(schema, schemaId)
262+
const derefSchema = refResolver.getDerefSchema(schemaId)
263+
264+
assert.deepStrictEqual(derefSchema, {
265+
type: 'object',
266+
definitions: {
267+
id1: {
268+
type: 'object',
269+
properties: {
270+
id1: {
271+
type: 'integer'
272+
}
273+
}
274+
}
275+
},
276+
allOf: [
277+
{
278+
type: 'object',
279+
properties: {
280+
id1: {
281+
type: 'integer'
282+
}
283+
}
284+
}
285+
]
286+
})
287+
})

0 commit comments

Comments
 (0)