futurechan / gulp-asset-transform

13 stars 3 forks source link

Validate configuration (issue #8) #11

Closed danilo-valente closed 9 years ago

danilo-valente commented 9 years ago

Added Joi schema to validate configuration objects. Solves #8.

futurechan commented 9 years ago

Thanks for the PR and your hard work.

A few things:

By the way, what do you think of joi?

danilo-valente commented 9 years ago

Yeah, I just realized that I forgot to add unit tests. About throwing a gutil.PluginError, I think it works, but I'll check to be sure. I loved Joi, it's pretty simple and easy to use.

danilo-valente commented 9 years ago

I've found this article, written by Gulp's staff. It says errors might be thrown, but only from within plugin level functions, which means I was doing wrong. But now, since the validation will be moved to index.js, I think it's a good idea to validate the configuration object before creating the stream object (through.obj), and then throw a PluginError in case of bad configuration.

danilo-valente commented 9 years ago

I have a question: In the old code, I had to validate a block configuration, which means this object:

{
    tasks:[less(), minifyCss(), 'concat']
}

But now, I have this object:

{
     id1: {
         tasks:[less(), minifyCss(), 'concat']
    },
    id2: {
        tasks:[uglify(), 'concat']
    }
}

So, what's the best way to validate each block config? Does Joi have some flag to validate each property with given schema? Should I iterate over this object and joi.validate each property?

futurechan commented 9 years ago

You can compose schemas from schemas. Try this: https://github.com/hapijs/joi#objectkeysschema

danilo-valente commented 9 years ago

I know, but the user can define any id, so I need a schema that applies to any property of the config object. Something like:

var configSchema = joi.object().keys({
    id1: blockConfigSchema,
    id2: blockConfigSchema
}).unknown();

But I can't explicitly assign to id1 and id2 because they are user-defined.

futurechan commented 9 years ago

The walmart guys are pretty quick with responses, especially in the irc. I'd recommend raising the issue there as I'd think this would be a very common use case.

For now, we could try something like this:

function validate(config, cb){  
    try{
        Object.keys(config).forEach(function(key){
            var transConfig = config[key];

            joi.assert(transConfig, transConfigSchema, 'Invalid schema in pipeline: ' + key + '\n');
        })      
    }catch(ex){
        cb(ex);
    }

    cb(null)
}
danilo-valente commented 9 years ago

Yeah, I did something like this too. I'll post there and see if they have a solution.

futurechan commented 9 years ago

Yeah, it's like they need an joi.object().values(...);

danilo-valente commented 9 years ago

Done. I've resolved the conflicts. Now:

I kept throwing the PluginError instead of emitting it because the validation occurs before the creation of the stream object.

futurechan commented 9 years ago

Excellent work!