Skip to content

Latest commit

 

History

History
325 lines (247 loc) · 12.9 KB

API.md

File metadata and controls

325 lines (247 loc) · 12.9 KB

6.0.0 API Reference

Felicity

entityFor(schema, [options])

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

Constructor methods

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 to entityFor.
  • example([options]) - Returns a valid pseudo-randomly generated example Javascript Object based on the Constructor's prototype.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's prototype.schema. Returns the below validationObject unless callback is provided, in which case callback(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 validation
      • value - 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  : {/*...*/}
      }

Instance methods

The new instances of the Constructor function returned by entityFor have the following properties/methods available.

  • schema - The Joi schema provided to entityFor. Non-enumerable, inherited from the Constructor.

  • example([options]) - Returns a new valid pseudo-randomly generated example Javascript Object based on the instance's schema property. Accepts an optional [options] parameter.

    Does not modify the instance.

  • validate([callback]) - Joi-validates the instance against the instance's schema property. Returns the same validationObject as the Constructor.validate method unless callback is provided, in which case callback(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'}}

example(schema, [options])

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' ]
}
*/

Options

All options parameters must be an object with property config. Properties on the config object are detailed by method below.

entityFor Options

  • strictInput - default false. 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 - default false. 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 - Default false. 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 - Default false. 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 - Default false. 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]

example Options

  • strictExample - default false. 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 - Default false. 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 - Default false. 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 - Default false. 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' }