Joi: Schema validation using instanceof breaks compatibility between modules

Created on 27 Jul 2017  路  9Comments  路  Source: sideway/joi

Context

  • node version: 7
  • joi version: 10.6
  • environment: node
  • any other relevant information: used between several modules

What are you trying to achieve or the steps to reproduce ?

Using instanceof to check if certain schema is a valid joi schema can lead to problems where you use different modules that export joi schemas. This is done for example on concat.js

Imagine that you use module-A, and module-B, both exporting a joi schema of the same version, and them you want to mix them in some way. Because concat.js checks if the schema to merge is an instanceof internals.Any it will fail. This is because how node handles dependencies, and how instanceof works: If two instances of the same class are generated using classes exported from files that resolve to different packages, they will not be considered being of the same class.

Example structure

    |- module a
        |- index.js <-- exports a joi schema
        |- node_modules
            |- joi 10.6
    |- module b
        |- index.js <-- exports a joi schema
        |- node_modules
            |- joi 10.6

then if you do something like this

a = require('a')
b = require('b')
joi = require('joi')

Joi.object().keys({ 
  x: Joi.number(),
  z: Joi.when('x', { is: 'a', then: a, otherwhise: b})
 })

It will fail because your Joi object is different from the joi object a is using, and different from the joi object b is using. The same happens if B requires A and tries to combine with any schema it has

Which result you had ?

An error telling that my schema is not a valid joi schema, which is not true.

What did you expect ?

Any other kind of checking, maybe looking for the isJoi flag or some other internal structure.

support

Most helpful comment

Exactly, there's no sane way to fix it so I'd rather not.

All 9 comments

I'm aware of it and reluctant to act on it. There has been problems in the past about mixed versions of joi used in the same schema, usually resulting in very obscure stack traces, but I can't guarantee the safety and validity of the validations that would occur while doing that, so I'm tempted to not fix this.

Hello @Marsup
I understand your position. however, this does not only happen with different versions of Joi, but also with the same version being resolved to different folders. I understand that offering compatibility between versions could be problematic, but in that case you can include a second flag with the version. I don't see why would you want to force every part of the code to use the same joi package resolved to the same folder, as soon as they are the same version

Same version should be deduped by npm. What's your suggestion ? Validating all joi schemas versions on every operation ? isJoi is not an option.

i just got burned by this as well.

i have found naively that commenting out this line allows my basic test case to pass, but i'm sure this has other implications.

fwiw, i'm specifying joi as a peerDependency in the exporting module.

Exactly, there's no sane way to fix it so I'd rather not.

thanks @Marsup , since you are far more intimate with the design than i, for my edification and thinking through any potential options, can you help me out a little with:

  1. what are the downsides of something like isJoi (i.e. used v instanceof in this line)?
  2. what are the downsides of removing this line altogether?

isJoi doesn't prevent the version conflict I mentioned above, I cannot guarantee the safety of joi with mixed versions inside the same schema.
By removing this line you allow this, so do it at your own risk.

on the bright side, things seem to work ok if modules specify joi in peerDependencies and/or devDependencies.

i am still having issues during local development when using yarn link tho as there is a local module version of joi at the linked-to module, which gets resolved and AssertionError [ERR_ASSERTION]: Invalid schema object is thrown.

this side-effect goes away when the module is deployed to npm without the "transient" linked-to version of joi, but it prevents the use of yarn link development strategies.

do you have a link to a thread discussing the version-conflicts you mentioned?

if the triggers are edge-casey, perhaps you would consider a use-at-your-own-risk opt-in for a kind of relaxed-mode which could perhaps back-off to isJoi?

I don't see the problem in including the version along with the isJoi property.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

leore picture leore  路  4Comments

farwayer picture farwayer  路  3Comments

PaunPrashant picture PaunPrashant  路  3Comments

ashrafkm picture ashrafkm  路  3Comments

REBELinBLUE picture REBELinBLUE  路  3Comments