svelte-jsoneditor icon indicating copy to clipboard operation
svelte-jsoneditor copied to clipboard

Using Ajv extentions with createAjvValidator.

Open TeaDrinkingProgrammer opened this issue 2 years ago • 1 comments

I would like to use the default Ajv validator with custom errormessages (using this Ajv extention. There seems no way to use extentions with the default createAjvValidator method, however. Would it be possible to add this functionality or, if that is too much work/not a priority, make a snippet explaining how this can be done? I tried making my own Ajv validator but there is no documentation for this and I couldn't get it to work.

TeaDrinkingProgrammer avatar Oct 18 '22 12:10 TeaDrinkingProgrammer

You can find the code of createAjvValidator here: /src/lib/plugins/validator/createAjvValidator.ts. You can just copy that code and change it to your needs. It could be interesting to think though if we can make the provided createAjvValidator a bit more flexible, so you can for example pass you're own ajv instance or can hook up an extension like the one you're using. I'm open to proposals.

What JSONEditor expects when you configure a validator is something of type Validator: a function that has the JSON document as input, and a list with errors as output.

https://github.com/josdejong/svelte-jsoneditor/blob/8f678228eb2c7e17e968ce38e573fa2a0e17b8d0/src/lib/types.ts#L175

josdejong avatar Oct 19 '22 11:10 josdejong

It would be great if addFormats(ajv) (https://ajv.js.org/packages/ajv-formats.html#usage) is added to createAjvValidator, because current "default" behavior does not support format JSONSchema keyword at all (no formats are supported out of the box, they are in a separate plugin). So when passing a schema with any "format" option, an unhandled error is raised.

ekzobrain avatar Oct 22 '22 17:10 ekzobrain

Yes that makes sense. Ideally, you have access to the created ajv instance to invoke methods like addFormats

Maybe we can introduce a forth, optional argument allowing to pass a callback onCreateAjv. This callback can be used to invoke addFormats and other methods, or you can even return a different ajv instance if you want.

export function createAjvValidator(
  schema: JSONValue,
  schemaDefinitions?: JSONValue,
  ajvOptions?: Options,
  onCreateAjv?: (ajv: Ajv) => Ajv | undefined
): Validator {
  // ...
}

Having four arguments of which three are optional is a bit ugly, so I think we should wrap this into an object so we have named parameters and no required order, like:

export function createAjvValidator({
  schema: JSONValue,
  schemaDefinitions?: JSONValue,
  ajvOptions?: Options,
  onCreateAjv?: (ajv: Ajv) => Ajv | undefined
}): Validator {
  // ...
}

What do you think?

josdejong avatar Oct 24 '22 07:10 josdejong

That sound good. However if ajv instance is not passed, addFormats() should be anyway called on created instance, otherwise most schemas are not recognized by default validator. Even with simple "date" format.

ekzobrain avatar Oct 25 '22 07:10 ekzobrain

Yes indeed, so you can use this calllback onCreateAjv in two ways:

  1. do some additional configuration on the provided ajv instance:
    function onCreateAjv(ajv: Ajv) {
      ajv.addFormats(...)
    }
    
  2. create your own ajv instance and ignore the provided ajv instance:
    function onCreateAjv(ajv: Ajv) {
      const myAjv = new Ajv(...)
      myAjv.addFormats(...)
      return myAjv
    }
    

josdejong avatar Oct 25 '22 09:10 josdejong

This looks like a very clean solutions, because one of the problems I encountered as well, is that you would need to import Ajv seperately from svelte-jsoneditor or install it again via npm to customise it. This way, you would only have to install the plugin and add it inside the function.

TeaDrinkingProgrammer avatar Oct 25 '22 15:10 TeaDrinkingProgrammer

The new onCreateAjv callback is implemented now in v0.10.0.

josdejong avatar Nov 10 '22 09:11 josdejong