/**
* @summary validation-function
*
* @version 3.0.0
* @since 1.0.0
* @author Arian Khosravi <arian.khosravi@aofl.com>
*/
/**
* ValidationFunction implementation
*
* @memberof module:@aofl/form-validate
*/
class ValidationFunction {
/**
* Creates an instance of ValidationFunction.
*
* @param {Object} target
* @param {Object} validatorFn
* @param {String} path
*/
constructor(target, validatorFn, path) {
Object.defineProperties(this, {
target: {
value: target
},
propName: {
value: path
},
resolve: {
writable: true
},
cachedPromise: {
writable: true
},
validateCompletePromise: {
writable: true
},
valid: {
writable: true
},
observed: {
writable: true
},
pending: {
writable: true
},
validatorFn: {
value: validatorFn
}
});
this.reset();
}
/**
*
*/
reset() {
this.cachedPromise = null;
this.resolve = null;
this.valid = true;
this.observed = false;
this.pending = false;
this.validateCompletePromise = null;
}
/**
*
*
*/
validate() {
this.observed = true;
let target = this.target; // @todo: move to object utils
const propChain = this.propName.split('.');
for (let i = 0; i < propChain.length - 1; i++) {
target = target[propChain[i]];
}
const promise = Promise.resolve(this.validatorFn(target));
this.cachedPromise = promise;
if (this.pending === false) {
this.validateCompletePromise = new Promise((resolve) => {
this.resolve = resolve;
});
}
this.pending = true;
promise
.then((valid) => {
if (this.cachedPromise === promise) { // latest update
this.valid = valid;
this.pending = false;
this.resolve();
this.target.requestUpdate();
}
});
}
/**
* @type {Promise}
*/
get validateComplete() {
return this.validateCompletePromise;
}
/* istanbul ignore next */
/**
*
* @return {Array}
*/
getKeys() {
const keys = ['valid', 'pending', 'observed'];
for (const key in this) {
if (!Object.prototype.hasOwnProperty.call(this, key)) continue;
keys.push(key);
}
return keys;
}
/* istanbul ignore next */
/**
* @return {String}
*/
toString() {
const keys = this.getKeys();
return JSON.stringify(this, keys, 2);
}
}
export {
ValidationFunction
};