Skip to content
8 changes: 4 additions & 4 deletions src/utils/getSchemaType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,12 @@ export function getSchemaType(node: SchemaNode, data: unknown): SchemaType | und

// nothing found yet check dynamic properties for a type
if (node.if) {
return getSchemaType(node.if, data);
return getSchemaType(node.if.getNode("#").node ?? node.if, data);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is out of scope of this merge request. I am wondering, why are you adding ref-resolution here?

If we were to add this:

  • getNode would need data as second argument to fully use its api
  • I would prefer to use node.if.resolveRef here to be explicit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the short story here is that first I realised that types of getSchemaType are off, so I fixed them and created this PR, later while working on my product I've seen that the function is also not working correctly on oneOf nodes with refs, so I thought this PR is close enough to include this as well... If you prefer I can split this into two PRs (or we can keep it as single one if that's ok)

as for node.if.resolveRef - I think it should work... I pushed the changes about that, are those ok?
and if you won't mind - what's the real benefit of using resolveRef here? I think that getNode looks to be way more generic way of "get me whatever there is underneath" right? under the hood it's also looks to handle more edge cases than resolveRef 🤔

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is one more issue here:

  • with resolveRef I have errors in current tests
 Exception during run: TypeError: Cannot read properties of undefined (reading 'length')
    at resolveRecursiveRef (/projects/json-schema-library/src/draft2019-09/keywords/$ref.ts:108:26)
    at Object.resolveRef (/projects/json-schema-library/src/draft2019-09/keywords/$ref.ts:75:26)
    at getSchemaType (/projects/json-schema-library/src/utils/getSchemaType.ts:132:66)
    at Object.getData (/projects/json-schema-library/src/draft2019-09/methods/getData.ts:174:31)
    at Object.getData (/projects/json-schema-library/src/SchemaNode.ts:305:37)
    at /projects/json-schema-library/src/draft2019-09/methods/getData.ts:200:56
    at Array.forEach (<anonymous>)
    at Object.object (/projects/json-schema-library/src/draft2019-09/methods/getData.ts:193:42)
    at Object.getData (/projects/json-schema-library/src/draft2019-09/methods/getData.ts:175:38)
    at Object.getData (/projects/json-schema-library/src/SchemaNode.ts:305:37)
    at Object.getData (/projects/json-schema-library/src/draft2019-09/methods/getData.ts:161:36)
    at Object.getData (/projects/json-schema-library/src/SchemaNode.ts:305:37)
    at /projects/json-schema-library/src/draft2019-09/methods/getData.ts:126:39
    at Array.forEach (<anonymous>)
    at Object.getData (/projects/json-schema-library/src/draft2019-09/methods/getData.ts:125:27)
    at Object.getData (/projects/json-schema-library/src/SchemaNode.ts:305:37)
    at compileSchema (/projects/json-schema-library/src/compileSchema.ts:74:58)
    at /projects/json-schema-library/src/tests/utils/runTestCases.ts:26:39
    at Array.forEach (<anonymous>)
    at Suite.<anonymous> (/projects/json-schema-library/src/tests/utils/runTestCases.ts:22:22)
    at Object.create (/projects/json-schema-library/node_modules/mocha/lib/interfaces/common.js:148:19)
    at context.describe.context.context (/projects/json-schema-library/node_modules/mocha/lib/interfaces/bdd.js:42:27)
    at runTestCase (/projects/json-schema-library/src/tests/utils/runTestCases.ts:21:5)
    at /projects/json-schema-library/src/tests/utils/runTestCases.ts:103:30
    at Array.forEach (<anonymous>)
    at Suite.<anonymous> (/projects/json-schema-library/src/tests/utils/runTestCases.ts:103:14)
    at Object.create (/projects/json-schema-library/node_modules/mocha/lib/interfaces/common.js:148:19)
    at context.describe.context.context (/projects/json-schema-library/node_modules/mocha/lib/interfaces/bdd.js:42:27)
    at runAllTestCases (/projects/json-schema-library/src/tests/utils/runTestCases.ts:89:5)
    at Object.<anonymous> (/projects/json-schema-library/src/tests/spec/draft2019-09.spec.ts:10:16)
  • with getNode everything works correctly

I don't have a root cause of the error yet

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am unable to reproduce issues based your tests:
On your branch, using

const type = getSchemaType(node.allOf[i].resolveRef(), data);
if (type) {
    return type;
}

works just fine on my end.

getNode does a couple of things in addition to resolving refs, like

  • parsing the json-pointer to find the node we are looking for and
  • creating additional an extended response type for consumption.

We can save unnecessary work and simply use resolveRef. Especially since this is a core function we should be explicit on the actions we use and work on the simpler api.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm... maybe I'm running tests somehow wrongly... I'm just executing yarn test

but I don't know how it could work tbh...
I see quite clear bug in src/draft2019-09/keywords/$ref.ts in resolveRef function (line 72). It has optional path param, that I'm not providing to it (as it's optional and I don't need it). Then on line 75 it's calling resolveRecursiveRef with that optional path as second parameter, which is not optional in resolveRecursiveRef declaration (src/draft2019-09/keywords/$ref.ts:102-103), which obviously results in error on line 108 where it tries to do history.length with history being undefined.
I fixed that bug by providing empty path in src/draft2019-09/keywords/$ref.ts and then I used resolveRef in getSchemaType. Now it should all be good

}

if (node.allOf) {
for (let i = 0; i < node.allOf.length; i += 1) {
const type = getSchemaType(node.allOf[i], data);
const type = getSchemaType(node.allOf[i].getNode("#").node ?? node.allOf[i], data);
if (type) {
return type;
}
Expand All @@ -120,7 +120,7 @@ export function getSchemaType(node: SchemaNode, data: unknown): SchemaType | und

if (node.oneOf) {
for (let i = 0; i < node.oneOf.length; i += 1) {
const type = getSchemaType(node.oneOf[i], data);
const type = getSchemaType(node.oneOf[i].getNode("#").node ?? node.oneOf[i], data);
if (type) {
return type;
}
Expand All @@ -129,7 +129,7 @@ export function getSchemaType(node: SchemaNode, data: unknown): SchemaType | und

if (node.anyOf) {
for (let i = 0; i < node.anyOf.length; i += 1) {
const type = getSchemaType(node.anyOf[i], data);
const type = getSchemaType(node.anyOf[i].getNode("#").node ?? node.anyOf[i], data);
if (type) {
return type;
}
Expand Down