Creates a Constructor function based on the provided Joi schema. Accepts an optional [options]
parameter.
Please note that JavaScript constructor functions only return objects. Therefore, the Joi schema provided must describe an object.
Instances created by new Constructor()
are "empty skeletons" of the provided Joi schema, and have sugary prototypal methods.
The returned Constructor function has the signature ([input], [options])
. Any input provided will be used to hydrate the new
object.
const schema = Joi.object().keys({
name: Joi.string().min(3).required(),
id : Joi.string().guid().required(),
keys: Joi.array().items(Joi.object().keys({id: Joi.string().guid()})).min(3).required()
});
const Conversation = Felicity.entityFor(schema);
const convoInstance = new Conversation();
const partialInstance = new Conversation({name: 'Felicity', fakeKey: 'invalid'});
/*
convoInstance
{
name: null,
id : null,
keys: []
}
partialInstance
{
name : 'Felicity',
id : null,
keys : [],
fakeKey: 'invalid'
}
*/
const nonObjectSchema = Joi.number();
const NeverGonnaHappen = Felicity.entityFor(nonObjectSchema); // throws Error 'Joi schema must describe an object for constructor functions'
The returned Constructor is also registered within the runtime with the exact name of Constructor. This can be corrected using the ES6 class extend
expression.
const schema = Joi.object().keys({
id : Joi.number().required(),
name: Joi.string().required()
});
const User = Felicity.entityFor(schema);
new User() // constructor will be of name Constructor
const User = class User extends Felicity.entityFor(schema);
new User() // constructor will be of name User
The Constructor function returned by entityFor
has the following properties/methods available for use without instantiation of new
objects.
prototype.schema
- The Joi validation schema provided toentityFor
.example([options])
- Returns a valid pseudo-randomly generated example Javascript Object based on the Constructor'sprototype.schema
. Accepts an optional[options]
parameter.// using schema and Conversation constructor from "entityFor" code example: const exampleConversation = Conversation.example(); /* exampleConversation { name: 'taut9', id : 'b227cd4c-4e7a-4ba4-a613-30747f7267b8', keys: [ { id: '401a7324-8753-4ae2-abcc-6ae96216500e' }, { id: 'c83c4a88-db1e-4402-8345-8b92be551b4e' }, { id: 'e4194c87-541c-41f7-9473-783bf0e790fe' } ] } */
validate(input, [callback])
- Joi-validates the provided input against the Constructor'sprototype.schema
. Returns the below validationObject unlesscallback
is provided, in which casecallback(errors, validationObject)
is called.validationObject
- the result of Joi validation has properties:success
- boolean.true
if Joi validation is successful,false
if input fails Joi validation.errors
- null if successful validation, array of all Joi validation error details if unsuccessful validationvalue
- Validated input value after any native Joi type conversion is applied (if applicable. see Joi docs for more details)
// Examples const successValidationObject = { success: true, errors : null, value : {/*...*/} } const failureValidationObject = { success: false, errors : [ { message: '"name" is required', path: 'name', type: 'any.required', context: { key: 'name' } } ], value : {/*...*/} }
The new
instances of the Constructor function returned by entityFor
have the following properties/methods available.
-
schema
- The Joi schema provided toentityFor
. Non-enumerable, inherited from the Constructor. -
example([options])
- Returns a new valid pseudo-randomly generated example Javascript Object based on the instance'sschema
property. Accepts an optional[options]
parameter.Does not modify the instance.
-
validate([callback])
- Joi-validates the instance against the instance'sschema
property. Returns the same validationObject as theConstructor.validate
method unlesscallback
is provided, in which casecallback(errors, validationObject)
is called.
const schema = Joi.object().keys({
name: Joi.string().required(),
id : Joi.string().guid().required()
);
const Constructor = Felicity.entityFor(schema);
const instance = new Constructor(); // instance === { name: null, id: null }
const instanceValidation = instance.validate(); // instanceValidation === { success: false, errors: [ { message: '"name" must be a string', path: 'name', type: 'string.base', context: [Object] },{ message: '"id" must be a string', path: 'id', type: 'string.base', context: [Object] }], value: {name: null, id: null} }
instance.name = 'Felicity';
instance.id = 'e7db5468-2551-4e42-98ea-47cc57606258';
const retryValidation = instance.validate(); // retryValidation === { success: true, errors: null, value: {name: 'Felicity', id: 'e7db5468-2551-4e42-98ea-47cc57606258'}}
Returns a valid pseudo-randomly generated example Javascript Object based on the provided Joi schema.
Accepts an optional [options]
parameter.
const schema = Joi.object().keys({
name: Joi.string().min(3).required(),
id : Joi.string().guid().required(),
tags: Joi.array().items(Joi.string().max(4)).min(2).required(),
});
const exampleDoc = Felicity.example(schema);
/*
exampleDoc
{
name: 'qgrbddv',
id : '6928f0c0-68fa-4b6f-9bc5-961db17d42b0',
tags: [ 'k2a', '31' ]
}
*/
All options parameters must be an object with property config
. Properties on the config
object are detailed by method below.
strictInput
- defaultfalse
. Default behavior is to not run known properties through Joi validation upon object instantiation.
If set to true
, all input will be validated, and only properties that pass validation will be utilized on the returned object.
All others will be returned in nulled/emptied form as if there was no input for that field.
Note: this will not throw Joi ValidationError
s. See validateInput
for error throwing.
const schema = Joi.object().keys({
id: Joi.string().guid()
});
const input = {
id: '12345678' // not a valid GUID
};
const Document = Felicity.entityFor(schema);
const document = new Document(input); // { id: '12345678' }
const StrictDocument = Felicity.entityFor(schema, { config: { strictInput: true } });
const strictDocument = new StrictDocument(input); // { id: null }
strictExample
- defaultfalse
. Default behavior is to not run examples through Joi validation before returning.
If set to true
, example will be validated prior to returning.
Note: in most cases, there is no difference. The only known cases where this may result in ValidationErrors are with regex patterns containing lookarounds.
const schema = Joi.object().keys({
name : Joi.string().regex(/abcd(?=efg)/)
});
const instance = new (Felicity.entityFor(schema)); // instance === { name: null }
const mockInstance = instance.example(); // mockInstance === { name: 'abcd' }
const strictInstance = new (Felicity.entityFor(schema, { config: { strictExample: true } })); // strictInstance === { name: null }
const mockStrict = strictInstance.example(); // ValidationError
ignoreDefaults
- Defaultfalse
. Default behavior is to stamp instances with defaults.
If set to true
, then default values of Joi properties with .default('value')
set will not be stamped into instances.
const schema = Joi.object().keys({
name: Joi.string().required().default('felicity')
});
const Constructor = Felicity.entityFor(schema);
const instance = new Constructor(); // instance === { name: 'felicity' }
const NoDefaults = Felicity.entityFor(schema, { config: { ignoreDefaults: true } });
const noDefaultInstance = new NoDefaults(); // noDefaultInstance === { name: null }
includeOptional
- Defaultfalse
. Default behavior is to ignore optional properties entirely.
If set to true
, then Joi properties with .optional()
set will be included on instances.
const schema = Joi.object().keys({
name : Joi.string().required(),
nickname: Joi.string().optional()
});
const Constructor = Felicity.entityFor(schema);
const instance = new Constructor(); // instance === { name: null }
const WithOptional = Felicity.entityFor(schema, { config: { includeOptional: true } });
const withOptionalInstance = new WithOptional(); // withOptionalInstance === { name: null, nickname: null }
validateInput
- Defaultfalse
. Default behavior is to not throw errors if input is not valid.
If set to true
, then invalid input passed to the constructor function will result in a thrown ValidationError
.
const schema = Joi.object().keys({
name : Joi.string()
});
const Constructor = Felicity.entityFor(schema);
const instance = new Constructor({ name: 12345 }); // instance === { name: 12345 }
const WithValidateInput = Felicity.entityFor(schema, { config: { validateInput: true } });
const withValidateInputInstance = new WithValidateInput({ name: 12345 }); // throws ValidationError: child "name" fails because ["name" must be a string]
strictExample
- defaultfalse
. Default behavior is to not run examples through Joi validation before returning.
If set to true
, example will be validated prior to returning.
Note: in most cases, there is no difference. The only known cases where this may result in no example coming back are with regex patterns containing lookarounds.
const schema = Joi.object().keys({
name : Joi.string().regex(/abcd(?=efg)/)
});
const instance = Felicity.example(schema); // instance === { name: 'abcd' }
const strictInstance = Felicity.example(schema, { config: { strictExample: true } }); // throws ValidationError
ignoreDefaults
- Defaultfalse
. Default behavior is to stamp instances with default values.
If set to true
, then default values of Joi properties with .default('value')
set will not be stamped into instances but will be generated according to the Joi property rules.
const schema = Joi.object().keys({
name: Joi.string().required().default('felicity')
});
const example = Felicity.example(schema); // example === { name: 'felicity' }
const noDefaultsExample = Felicity.example(schema, { config: { ignoreDefaults: true } }); // noDefaultsExample === { name: 'nq5yhu4ttq33di' }
ignoreValids
- Defaultfalse
. Default behavior is to pick values from.allow()
ed and.valid()
sets.
If set to true
, then the allowed/valid values will not be used but will be generated according to the Joi property rules.
const schema = Joi.object().keys({
name: Joi.string().allow(null).required()
});
const example = Felicity.example(schema); // example === { name: null }
const noValidsExample = Felicity.example(schema, { config: { ignoreValids: true } }); // noValidsExample === { name: 'nq5yhu4ttq33di' }
includeOptional
- Defaultfalse
. Default behavior is to ignore optional properties entirely.
If set to true
, then Joi properties with .optional()
set will be included on examples.
const schema = Joi.object().keys({
name : Joi.string().required(),
nickname: Joi.string().optional()
});
const instance = Felicity.example(schema); // instance === { name: 'ml9mmn0r8m7snhfr' }
const withOptional = Felicity.example(schema, { config: { includeOptional: true } }); // withOptional === { name: '3cpffhgccgsw0zfr', nickname: '7pfjuxfa4gxk1emi' }