hyperjump-io / json-schema-bundle

A tool for bundling JSON Schema documents
MIT License
14 stars 1 forks source link

Additional Properties causes TypeError when gathering externalIds #6

Closed gavinbarron closed 2 years ago

gavinbarron commented 2 years ago

Opening this as a new issue related to #5

In my previous report I had mistakenly put the additionalProperties as a child of properties, not a sibling as it should be: ref

Using this loader code in webpack

const Bundler = require('@hyperjump/json-schema-bundler');

async function loader(content, map, meta) {
    if (this.cacheable) this.cacheable();
    var callback = this.async();
    const logger = this.getLogger();
    const schemaPath = this.resourcePath;
    const match = new RegExp(/\.json$/).test(schemaPath);
    if (match) {
        const schemaFileUri = `file://${schemaPath}`;
        logger.warn(schemaFileUri);
        try {
            const main = await Bundler.get(schemaFileUri);
            const bundle = await Bundler.bundle(main);
            const result = JSON.stringify(bundle);
            callback(null, result, map, meta);
            return result;
        } catch (error) {
            logger.error(error);
        }
    }
    callback(null, content, map, meta);
    return content;
}

module.exports = loader;

With these schema

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "pageProperties.schema.json",
  "type": "object",
  "properties": {
    "blockedScope": {
      "type": "array",
      "items": {
        "$ref": "scope.schema.json#/$defs/Scope"
      }
    },
    "darkTheme": {
      "type": "boolean"
    }
  },
  "additionalProperties": false
}
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "scope.schema.json",
  "$defs": {
    "Scope": {
      "type": "string",
      "enum": [
        "user",
        "tools",
        "admin",
        "editor"
      ]
    }
  }
}

Results in this error:

<e> TypeError: Value at '/definitions' is undefined and does not have property 'Scope'
<e>     at applySegment (/home/gavinb/dev/events/client/node_modules/@hyperjump/json-pointer/lib/index.js:120:11)
<e>     at /home/gavinb/dev/events/client/node_modules/@hyperjump/json-pointer/lib/index.js:18:13
<e>     at Array.reduce (<anonymous>)
<e>     at fn (/home/gavinb/dev/events/client/node_modules/@hyperjump/json-pointer/lib/index.js:17:29)
<e>     at Object.get (/home/gavinb/dev/events/client/node_modules/@hyperjump/json-pointer/lib/index.js:21:37)
<e>     at get (/home/gavinb/dev/events/client/node_modules/@hyperjump/json-schema-core/lib/schema.js:185:24)
<e>     at followReferences (/home/gavinb/dev/events/client/node_modules/@hyperjump/json-schema-core/lib/schema.js:191:70)
<e>     at step (/home/gavinb/dev/events/client/node_modules/@hyperjump/json-schema-core/lib/schema.js:215:10)
<e>     at /home/gavinb/dev/events/client/node_modules/@hyperjump/json-schema-core/lib/schema.js:223:39
<e>     at Array.map (<anonymous>)

Inspecting the site of the error, const keywordId = ast[schemaUri][0];, I see that schemaUri is an array when the error occurs: image

While the ast is an object with string keys: image

At the next step up the call stack in keywords.js I can see that the nodes collection being iterated over contains an entry with the array that seems to be causing this issue: image

The naïve fix is to add a typeof check on to the recursion in addition to collectExternalIds

        if (keyword.collectExternalIds && typeof keywordValue === 'string') {
          keyword.collectExternalIds(keywordValue, externalIds, ast, dynamicAnchors);
        }

But I have no idea what the side effects of this would be or if that's even properly addressing this issue

jdesrosiers commented 2 years ago

I'm not able to reproduce the problem. It works for me.

The error you are seeing doesn't appear to be related to your example schemas. It's telling you that you are using a JSON Pointer that starts with /definitions/Scope, but the /definitions location is undefined. That pointer doesn't appear anywhere in your schemas, so you must be running against some other schemas.

Your debugging points to be the problem that was fixed in v0.1.2. If you are actually running against v0.1.1, the error I would expect you to see is this.

  const keywordId = ast[schemaUri][0];
                                  ^

TypeError: Cannot read properties of undefined (reading '0')

Can you check node_modules/@hyperjump/json-schema-bundle/package.json#/version to be absolutely sure which version you are working with?

gavinbarron commented 2 years ago

Dang it! despite me removing and re-adding yarn had me at v0.1.1 :(

The /definitions path is created by the bunder as it imports the $refs based on what I was seeing. Either way getting the upgraded package resolves the problem Apologies for the churn here.