Skip to content

Commit

Permalink
support dynamic defaults via registered callback functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike Eldridge committed Aug 28, 2019
1 parent 3a58dc5 commit af1a7ae
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 10 deletions.
26 changes: 23 additions & 3 deletions lib/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,30 @@ class BaseSchema {
this.engineFuncName = engineFuncName;
}

parse( config, engine ) {

parse( config, engine, functions ) {
// Note: Joi will clone objects on changes and thus we need to update the schema reference
let state = { schema: this._createSchema( engine ), engine };

for( let key in config ) {
let value = config[ key ];

// handle function default args
if( key === "default" ) {
const function_match = value.match( /^([a-zA-Z0-9_]+)\(([a-zA-Z0-9_.]+)\)$/ );

if( function_match ) {
const [ , function_name, function_args ] = function_match;
const f = functions.get( function_name );

if( f ) {
value = [ f.bind( null, function_args ), function_name ];
} else {
throw new Error( "unable to locate function with name: " + function_name );
}
}
}

this.updateSchema( state, key, config[ key ] );
this.updateSchema( state, key, value );
}

return state.schema;
Expand All @@ -30,6 +46,10 @@ class BaseSchema {

state.schema = state.schema[ key ]();
}
else if (Array.isArray(value)) {

state.schema = state.schema[ key ]( ...value );
}
else {

state.schema = state.schema[ key ]( value );
Expand Down
4 changes: 4 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class SchemaBuilder {
return schema;
}
}

registerFunction( name, f ) {
this.parser.registerFunction( name, f );
}
}

function resolveEngines() {
Expand Down
4 changes: 2 additions & 2 deletions lib/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class ObjectSchema extends BaseSchema {
this.parseSchema = parseSchema;
}

parse( config, engine ) {
parse( config, engine, functions ) {

// Note: Joi will clone objects on changes and thus we need to update the schema reference
let state = { schema: engine.object(), engine };
Expand All @@ -31,7 +31,7 @@ class ObjectSchema extends BaseSchema {
else {

// assume key
keys[ key ] = parseSchemaFunc.call( null, value, engine );
keys[ key ] = parseSchemaFunc.call( null, value, engine, functions );
}
}

Expand Down
17 changes: 14 additions & 3 deletions lib/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function parseSchemaString( str ) {
return schema;
}

function parseSchema( value, engine ) {
function parseSchema( value, engine, functions ) {

if( utils.isString( value ) ) {

Expand Down Expand Up @@ -124,7 +124,7 @@ function parseSchema( value, engine ) {
throw new Error( 'unknown type: ' + type );
}

return parser.parse( value, engine );
return parser.parse( value, engine, functions );
}

class Parser {
Expand All @@ -137,11 +137,22 @@ class Parser {
}

this.engine = engine;
this.functions = new Map();
}

parse( value ) {

return parseSchema( value, this.engine );
return parseSchema( value, this.engine, this.functions );
}

registerFunction( name, f ) {

this.functions.set( name, f );
}

getFunction( name ) {

this.functions.get( name );
}

static buildSchema( schemaConfig, engine ) {
Expand Down
4 changes: 2 additions & 2 deletions lib/string.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ class StringSchema extends BaseSchema {
super( 'string' );
}

parse( config, engine ) {
parse( config, engine, functions ) {

if( config.trim === null ) {

config.trim = true;
}

let schema = super.parse( config, engine );
let schema = super.parse( config, engine, functions );

if( config.trim === undefined ) {

Expand Down
11 changes: 11 additions & 0 deletions test/lib/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,5 +276,16 @@ describe( 'lib/index', function() {
let result3 = joi.validate( 'forty-two', schema );
expect( result3.error ).to.exist;
});

it( 'default functions', function() {

let f = function() { return parser.parse( 'string:default=some_function(ok)' ) };

expect( f ).to.throw(Error, "unable to locate function with name: some_function" );

parser.registerFunction("some_function", val => { result: true, val });

expect( f ).to.not.throw();
});
});
});

0 comments on commit af1a7ae

Please sign in to comment.