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

Not working for YAML schema's. #28

Closed webketje closed 1 year ago

webketje commented 1 year ago

I did as instructed adding a YAML mediaTypePlugin:

import { validate, addMediaTypePlugin } from '@hyperjump/json-schema/openapi-3-0'
import { pathToFileURL } from 'node:url'
import { join } from 'node:path'
import { load } from 'js-yaml'

const is31 = RegExp.prototype.test.bind(/^3\.1\.\d+(-.+)?$/)
const is30 = RegExp.prototype.test.bind(/^3\.0\.\d+(-.+)?$/)

addMediaTypePlugin("application/yaml", {
  parse: async (response, contentTypeParameters) => {
    const doc = load(await response.text());

    let defaultDialect;
    const version = doc.openapi || contentTypeParameters.version;

    if (!version) {
      throw Error("Invalid OpenAPI document. Add the 'openapi' field and try again.");
    } else if (is30(version)) {
      defaultDialect = "https://spec.openapis.org/oas/3.0/schema";
    } else if (is31(version)) {
      if (!("jsonSchemaDialect" in doc) || doc.jsonSchemaDialect === "https://spec.openapis.org/oas/3.1/dialect/base") {
        defaultDialect = "https://spec.openapis.org/oas/3.1/schema-base";
      } else {
        defaultDialect = `https://spec.openapis.org/oas/3.1/schema-${encodeURIComponent(doc.jsonSchemaDialect)}`;
      }
    } else {
      throw Error(`Encountered unsupported OpenAPI version '${version}' in ${response.url}`);
    }

    return [doc, defaultDialect];
  },
  matcher: (path) => /\.ya*ml$/.test(path)
});

const validSchema = await validate(pathToFileURL(join('doc', 'openapi_spec.yaml')))

But it always fails with

/node_modules/@hyperjump/json-schema/lib/schema.js:26 throw Error(Encountered unknown dialect '${dialectId}');

Also, manually navigating to all the default dialects are Github 404's..

When the defaultDialect is hardcoded to undefined as in the README example, it always throws. No idea why it even tries querying https://json-schema.org/validation

node_modules/@hyperjump/json-schema/lib/schema.js:172
      throw Error(`Failed to retrieve ${id} (${response.status} ${response.statusText})`);
            ^

Error: Failed to retrieve https://json-schema.org/validation (404 Not Found)
    at get (file:///C:/Users/johndoe/project/node_modules/@hyperjump/json-schema/lib/schema.js:172:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Module.get (file:///C:/Users/johndoe/project/node_modules/@hyperjump/json-schema/lib/schema.js:180:7)
    at async compile (file:///C:/Users/johndoe/project/node_modules/@hyperjump/json-schema/lib/core.js:27:18)
    at async validate (file:///C:/Users/johndoe/project/node_modules/@hyperjump/json-schema/lib/core.js:20:20)
    at async file:///C:/Users/johndoe/project/test.js:36:21
jdesrosiers commented 1 year ago

There was misconfiguration for OpenAPI 3.0. I just released v1.5.1 to fix the problem. When you update, the error should go away.

However, the next error you'll get is an InvalidSchemaError because you aren't quite using the API correctly. There are two things you can do and what you're doing is somewhere in the middle.

If you're just trying to validate the OpenAPI document, you want something like this,

const openapi = load(readFileSync("doc/openapi_spec.yaml", "utf8"))
const output = await validate("https://spec.openapis.org/oas/3.0/schema", openapi)
console.log(output.valid)

If you want a validator function for a schema in the OpenAPI document, you need to point to the schema you want.

const validateFoo = await validate(pathToFileURL("doc/openapi_spec.yaml") + "#/components/schemas/foo")
const output = validateFoo(42)
console.log(output.valid);

The second example will also validate your whole OpenAPI document and throw an InvalidSchemaError if there's a problem. So, you don't need to validate the OpenAPI document separately if you are using this feature.

webketje commented 1 year ago

Thanks, what I wanted to do was case 2: create a validator for a response in #/components/responses/ResponseType. I missed the part of the code snippet in the README where it shows the JSON schema ref being used within the validate method (but I saw it now). I'll reinstall & close the issue after validating :)