lib/Legitimate.js
import * as defaultValidators from './validators';
import * as defaultLocales from './locales';
const
rulesMap = new WeakMap(),
stateMap = new WeakMap(),
localesMap = new WeakMap(),
isPropProper = prop => {
if (typeof prop !== 'string') {
throw new Error('Given prop must be a valid string in order to update');
}
};
/**
* Merge unique
* @param response
*/
export const flattenResponse = response => new Promise((resolve, reject) => {
try {
if (typeof response !== 'object') {
throw new Error(`${response} should be object`);
}
if (response instanceof Array === false) {
return resolve(response);
}
resolve([...new Set([].concat(...response))]);
} catch (error) {
reject(error);
}
});
/**
* @class {class} Legitimate
* @classdesc Legitimate class to validate given state by updating and validating
*/
export class Legitimate {
/**
* @property state
* @readonly
* @description Returns the current state
* @type {object}
*/
get state() {
return stateMap.get(this);
}
/**
* @property rules
* @readonly
* @description Returns the current rules
* @type {object}
*/
get rules() {
return rulesMap.get(this);
}
/**
* @property locales
* @readonly
* @description Returns the current locales
* @type {object}
*/
get locales() {
return localesMap.get(this);
}
/**
* @constructor
* @param locales {object} [param=defaultLocales]
* @param initialState {object} [initialState={}]
*/
constructor(locales = defaultLocales, initialState = {}) {
rulesMap.set(this, Object.create(null));
stateMap.set(this, initialState);
localesMap.set(this, locales);
}
/**
* Sets validation functions for given prop
* @param prop
* @param rulesToAdd
* @returns {Legitimate}
*/
setRules(prop = false, ...rulesToAdd) {
isPropProper(prop);
rulesMap.set(this, { ...this.rules, [prop] : [...rulesToAdd] });
return this;
}
/**
* Updates the state by given prop and value
* @param prop {string}
* @param value {*}
* @returns {Legitimate}
*/
update(prop = false, value) {
isPropProper(prop);
stateMap
.set(this, { ...this.state, [prop] : value });
return this;
}
/**
* Triggers defined rules for prop
* @param prop
* @returns {Promise.<*>}
*/
validate(prop) {
return new Promise((resolve, reject) => {
isPropProper(prop);
Promise
.all(this.rules[prop].map(validator => validator(this.state[prop], this.locales)))
.then(flattenResponse)
.then(resolve)
.catch(response => flattenResponse(response)
.then(reject)
.catch(reject));
});
}
/**
* Validate all
* @returns {Promise.<*>}
*/
isLegit() {
return Promise
.all(Object.keys(this.rules).map(::this.validate))
.then(flattenResponse)
.then(::Promise.resolve)
.catch(response => {
return flattenResponse(response)
.then(::Promise.reject)
.catch(::Promise.reject);
});
}
}
export const
locales = defaultLocales,
validators = defaultValidators;
export default Legitimate;