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 UserThe 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 unlesscallbackis provided, in which casecallback(errors, validationObject)is called.validationObject- the result of Joi validation has properties:success- boolean.trueif Joi validation is successful,falseif 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'sschemaproperty. Accepts an optional[options]parameter.Does not modify the instance.
-
validate([callback])- Joi-validates the instance against the instance'sschemaproperty. Returns the same validationObject as theConstructor.validatemethod unlesscallbackis 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 ValidationErrors. 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(); // ValidationErrorignoreDefaults- 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 ValidationErrorignoreDefaults- 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' }