'use strict';
|
|
const Hoek = require('@hapi/hoek');
|
|
const Any = require('../any');
|
|
|
const internals = {};
|
|
|
internals.Lazy = class extends Any {
|
|
constructor() {
|
|
super();
|
this._type = 'lazy';
|
this._flags.once = true;
|
this._cache = null;
|
}
|
|
_init(fn, options) {
|
|
return this.set(fn, options);
|
}
|
|
_base(value, state, options) {
|
|
let schema;
|
if (this._cache) {
|
schema = this._cache;
|
}
|
else {
|
const result = { value };
|
const lazy = this._flags.lazy;
|
|
if (!lazy) {
|
result.errors = this.createError('lazy.base', null, state, options);
|
return result;
|
}
|
|
schema = lazy();
|
|
if (!(schema instanceof Any)) {
|
result.errors = this.createError('lazy.schema', { schema }, state, options);
|
return result;
|
}
|
|
if (this._flags.once) {
|
this._cache = schema;
|
}
|
}
|
|
return schema._validate(value, state, options);
|
}
|
|
set(fn, options) {
|
|
Hoek.assert(typeof fn === 'function', 'You must provide a function as first argument');
|
Hoek.assert(options === undefined || (options && typeof options === 'object' && !Array.isArray(options)), `Options must be an object`);
|
|
if (options) {
|
const unknownOptions = Object.keys(options).filter((key) => !['once'].includes(key));
|
Hoek.assert(unknownOptions.length === 0, `Options contain unknown keys: ${unknownOptions}`);
|
Hoek.assert(options.once === undefined || typeof options.once === 'boolean', 'Option "once" must be a boolean');
|
}
|
|
const obj = this.clone();
|
obj._flags.lazy = fn;
|
|
if (options && options.once !== obj._flags.once) {
|
obj._flags.once = options.once;
|
}
|
|
return obj;
|
}
|
|
};
|
|
module.exports = new internals.Lazy();
|