hyperjump-io / json-schema

JSON Schema Validation, Annotation, and Bundling. Supports Draft 04, 06, 07, 2019-09, 2020-12, OpenAPI 3.0, and OpenAPI 3.1
https://json-schema.hyperjump.io/
MIT License
216 stars 22 forks source link

Always tries to fetch from web #29

Closed designermonkey closed 1 year ago

designermonkey commented 1 year ago

When I use this example code (modified from the readme):

import { addSchema } from "@hyperjump/json-schema/draft-2020-12";
import { bundle } from "@hyperjump/json-schema/bundle";
import * as yaml from 'yaml'

addSchema({
  "$id": "https://schema.datum.microntech.io/main",
  "$schema": "https://json-schema.org/draft/2020-12/schema",

  "type": "object",
  "properties": {
    "foo": { "$ref": "/string" }
  }
});

addSchema({
  "$id": "https://schema.datum.microntech.io/string",
  "$schema": "https://json-schema.org/draft/2020-12/schema",

  "type": "string"
});

const bundledSchema = await bundle("https://schema.datum.microntech.io/main"); // {
//   "$id": "https://schema.datum.microntech.io/main",
//   "$schema": "https://json-schema.org/draft/2020-12/schema",
//
//   "type": "object",
//   "properties": {
//     "foo": { "$ref": "/string" }
//   },
//
//   "$defs": {
//     "https://schema.datum.microntech.io/string": {
//       "$id": "https://schema.datum.microntech.io/string",
//       "type": "string"
//     }
//   }
// }

console.log(yaml.stringify(bundledSchema))

Then everything works as expected and I get output.

When I try any other code that uses my own schema files, which I have verified are being added to the schemaStore by the right IDs, then I always get an error that the url cannot be found.

Is there something special I need to do to make this work without having an actual domain name that hosts the files? Why would it work with two example schema but not with 50 real ones?

designermonkey commented 1 year ago

I can share the code I used if it would be helpful, but I can't share the schemas as they are proprietary at present.

jdesrosiers commented 1 year ago

It will only try to fetch the schema if it doesn't exist in the schemaStore. I don't have a lot of information to go on, so it's hard for me to help too much. When you get the error that he URL couldn't be found, it should tell you what the offending URL is, right? I'd start by trying to figure out why a schema with that URL isn't in the schemaStore and try to rectify that problem.

If you can provide more information, I'd be happy to try to help more. Sharing code and specific error messages might help, but I suspect there's not much I can figure out without seeing the schemas. If you're able to share over a private channel such as email or the JSON Schema Slack, I'd be happy to look it over. Otherwise I'd suggest trying to create a minimal reproducible example that you can share.

designermonkey commented 1 year ago

Is there any way to see what ID caused the fetch to be made? It may be a simple spelling mistake but with ~50 schemas it's going to be hard to track it down.

designermonkey commented 1 year ago

Ok so it was a minute spelling mistake on my part. That took some finding!

Thanks for your time on this though. It would be great to have some way of knowing where the error was being raised in terms of the schema as well as the calling code.

jdesrosiers commented 1 year ago

Can you share the exact error you were getting or a minimal reproduction of the error? I'd like to see what I can do about improving the experience, but that's hard to do unless I can reproduce that experience.

designermonkey commented 1 year ago

Here's a copy of the error caused by a mis-identified schema being referenced in another:

/reference/node_modules/undici/index.js:109
      Error.captureStackTrace(err, this)
            ^

TypeError: fetch failed
    at fetch (/reference/node_modules/undici/index.js:109:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Module.get (file:///reference/node_modules/@hyperjump/json-schema/lib/schema.js:167:22)
    at async Object.compile (file:///reference/node_modules/@hyperjump/json-schema/lib/keywords/ref.js:8:28)
    at async file:///reference/node_modules/@hyperjump/json-schema/lib/keywords/validation.js:49:28
    at async file:///reference/node_modules/@hyperjump/pact/lib/index.js:12:5
    at async asyncCollectArray (file:///reference/node_modules/@hyperjump/pact/lib/index.js:226:20)
    at async Object.compile (file:///reference/node_modules/@hyperjump/json-schema/lib/keywords/validation.js:33:65)
    at async Object.compile (file:///reference/node_modules/@hyperjump/json-schema/lib/keywords/items.js:15:32)
    at async file:///reference/node_modules/@hyperjump/json-schema/lib/keywords/validation.js:49:28 {
  cause: Error: getaddrinfo ENOTFOUND schema.datum.microntech.io
      at GetAddrInfoReqWrap.onlookupall [as oncomplete] (node:dns:118:26) {
    errno: -3008,
    code: 'ENOTFOUND',
    syscall: 'getaddrinfo',
    hostname: 'schema.datum.microntech.io'
  }
}

I've seen other errors about invalid schema that have an empty errors array when I use bundle as opposed to validate

file:///reference/node_modules/@hyperjump/json-schema/lib/core.js:103
      throw new InvalidSchemaError(metaResults);
            ^

InvalidSchemaError: Invalid Schema
    at Object.pubsub_subscription_0 (file:///reference/node_modules/@hyperjump/json-schema/lib/core.js:103:13)
    at publishAsync (file:///reference/node_modules/@hyperjump/json-schema/lib/pubsub.js:34:61)
    at Object.compile (file:///reference/node_modules/@hyperjump/json-schema/lib/keywords/validation.js:14:9)
    at compile (file:///reference/node_modules/@hyperjump/json-schema/lib/core.js:29:38)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async collectExternalIds (file:///reference/node_modules/@hyperjump/json-schema/bundle/index.js:61:30)
    at async bundle (file:///reference/node_modules/@hyperjump/json-schema/bundle/index.js:25:23)
    at async file:///reference/bundle.js:47:17 {
  output: {
    keyword: 'https://json-schema.org/evaluation/validate',
    absoluteKeywordLocation: 'https://json-schema.org/draft/2020-12/schema#',
    instanceLocation: 'https://schema.datum.microntech.io/api/arrange/relationship#',
    valid: false,
    errors: []
  }
}

That one made it hard to track down the errors.

I hope these help :)

jdesrosiers commented 1 year ago

This is helpful, thank you!

Here's a copy of the error caused by a mis-identified schema being referenced in another:

I get what the problem is now. The error is that the domain is unreachable, but it doesn't include the full URI, which makes it hard to track down the offending schema. I'll probably need to catch this error and return a more helpful one of my own.

I've seen other errors about invalid schema that have an empty errors array when I use bundle as opposed to validate.

You need to configure how you want errors to be presented. The default is the FLAG format that only provides pass/fail info. There are several output formats defined by the JSON Schema specification, but they aren't considered stable and may change. Therefore, I require you to opt-in if you want to use them. It's safe to use them for human consumption, but if you write code that depends on them, you need to accept the risk that they might change without warning.

This is something that has confused others as well. I'll see about adding some additional info to the error message to point people in the right direction.

designermonkey commented 1 year ago

Thanks for the feedback and info :)