korzio / djv

Dynamic JSON Schema Validator - Supports draft-04/06
https://www.npmjs.com/package/djv
MIT License
289 stars 31 forks source link

`date-time` format errors with number #95

Open bytesnz opened 4 years ago

bytesnz commented 4 years ago

Error

Given a numeric value, validating against a string schema with a date-time format, the validate template function for the date-time error throws an error.

Initially noticed on latest version (2.1.3-alpha.0), but also occurs on 2.1.2

Expected Result

It does not throw and returns a type error for the value if type: 'string' is set in the schema, otherwise, the format function should not be run (as format: 'date-time' is only valid against a string)

Example code

var djv = require("djv/lib/djv");

const env = new djv();
env.addSchema('Article', {
  type: 'object',
  properties: {
    type: {
      const: 'Article'
    },
    slug: {
      type: 'string',
      pattern: '^[a-z0-9-]*$'
    },
    published: {
      type: 'string',
      format: 'date-time'
    },
    summary: {
      type: 'string',
      contentType: 'text/markdown'
    }
  },
  required: [ 'type' ]
});

console.log(env.validate('Article', { type: 'Article' }));
console.log(env.validate('Article', { type: 'Article', published: '2020-01-01T12:00' }));
console.log(env.validate('Article', { type: 'Article', published: 'dsfds' }));
console.log(env.validate('Article', { type: 'Article', published: 42 }));

Output

undefined
undefined
{
  keyword: 'format',
  dataPath: '.published',
  schemaPath: '#/properties/published/format'
}

if (isNaN(Date.parse(data['published'])) || ~data['published'].indexOf('/')) return {
                                                               ^

TypeError: data.published.indexOf is not a function
    at Object.f0 [as fn] (eval at restore (node_modules/djv/lib/utils/template.js:125:15), <anonymous>:40:64)
    at Environment.validate (node_modules/djv/lib/djv.js:69:31)
    at Object.<anonymous> (djv.js:29:5)
    at Module._compile (internal/modules/cjs/loader.js:1133:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:10)
    at Module.load (internal/modules/cjs/loader.js:977:32)
    at Function.Module._load (internal/modules/cjs/loader.js:877:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)
    at internal/main/run_main_module.js:18:47

Fix

Happy to create PR for fix. Was going to:

So validator template would be

expression`typeof ${'data'} === 'string' && isNaN(Date.parse(${'data'}))`,

Example output would then be

undefined
undefined
{
  keyword: 'format',
  dataPath: '.published',
  schemaPath: '#/properties/published/format'
}
{
  keyword: 'type',
  dataPath: '.published',
  schemaPath: '#/properties/published/type'
}

Could also add the typeof ${'data'} === 'string' && to the other formats that require a string (all formats specified in the validation spec are only valid against a string and should succeed (be ignored) if the type is not a string)?