diff --git a/index.js b/index.js index 307474a..3458a51 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,10 @@ const { dequal: deepEqual } = require('dequal') const jsonSchemaRefSymbol = Symbol.for('json-schema-ref') +// the keywords whose value is data, not a schema: a $ref or an $id inside them is a property +// name of the instance, not a reference +const dataKeywords = new Set(['default', 'const', 'enum', 'examples']) + class RefResolver { #schemas #derefSchemas @@ -50,6 +54,7 @@ class RefResolver { } for (const key in schema) { + if (dataKeywords.has(key)) continue if (typeof schema[key] === 'object' && schema[key] !== null) { this.addSchema(schema[key], rootSchemaId, false) } @@ -202,6 +207,7 @@ class RefResolver { } for (const key in derefSchema) { + if (dataKeywords.has(key)) continue const value = derefSchema[key] if (typeof value === 'object' && value !== null) { derefSchema[key] = this.#addDerefSchema(value, rootSchemaId, false, refs) diff --git a/test/data-keywords.test.js b/test/data-keywords.test.js new file mode 100644 index 0000000..f6ac16f --- /dev/null +++ b/test/data-keywords.test.js @@ -0,0 +1,27 @@ +'use strict' + +const assert = require('node:assert/strict') +const { test } = require('node:test') +const { RefResolver } = require('../index.js') + +// a $ref inside default, const, enum or examples is a property of the instance, not a reference, +// and was collected as one: the dependencies could not be resolved and the deref walked into data +test('does not read a $ref inside a data keyword as a reference', () => { + const refResolver = new RefResolver() + const schema = { + $id: 'schemaId', + type: 'object', + properties: { + a: { type: 'object', default: { $ref: 'nowhere#/x', $id: 'nowhere' } }, + b: { const: { $ref: 'nowhere' } }, + c: { enum: [{ $ref: 'nowhere' }] }, + d: { type: 'string', examples: [{ $ref: 'nowhere' }] } + } + } + refResolver.addSchema(schema) + + assert.deepStrictEqual(refResolver.getSchemaRefs('schemaId'), []) + assert.deepStrictEqual(refResolver.getSchemaDependencies('schemaId'), {}) + assert.deepStrictEqual(refResolver.getDerefSchema('schemaId'), schema) + assert.equal(refResolver.hasSchema('nowhere'), false) +})