.
This commit is contained in:
		
							
								
								
									
										750
									
								
								qwen/nodejs/node_modules/joi/lib/validator.js
									
									
									
										generated
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										750
									
								
								qwen/nodejs/node_modules/joi/lib/validator.js
									
									
									
										generated
									
									
										vendored
									
									
										Executable file
									
								
							@@ -0,0 +1,750 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
const Assert = require('@hapi/hoek/lib/assert');
 | 
			
		||||
const Clone = require('@hapi/hoek/lib/clone');
 | 
			
		||||
const Ignore = require('@hapi/hoek/lib/ignore');
 | 
			
		||||
const Reach = require('@hapi/hoek/lib/reach');
 | 
			
		||||
 | 
			
		||||
const Common = require('./common');
 | 
			
		||||
const Errors = require('./errors');
 | 
			
		||||
const State = require('./state');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const internals = {
 | 
			
		||||
    result: Symbol('result')
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exports.entry = function (value, schema, prefs) {
 | 
			
		||||
 | 
			
		||||
    let settings = Common.defaults;
 | 
			
		||||
    if (prefs) {
 | 
			
		||||
        Assert(prefs.warnings === undefined, 'Cannot override warnings preference in synchronous validation');
 | 
			
		||||
        Assert(prefs.artifacts === undefined, 'Cannot override artifacts preference in synchronous validation');
 | 
			
		||||
        settings = Common.preferences(Common.defaults, prefs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const result = internals.entry(value, schema, settings);
 | 
			
		||||
    Assert(!result.mainstay.externals.length, 'Schema with external rules must use validateAsync()');
 | 
			
		||||
    const outcome = { value: result.value };
 | 
			
		||||
 | 
			
		||||
    if (result.error) {
 | 
			
		||||
        outcome.error = result.error;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (result.mainstay.warnings.length) {
 | 
			
		||||
        outcome.warning = Errors.details(result.mainstay.warnings);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (result.mainstay.debug) {
 | 
			
		||||
        outcome.debug = result.mainstay.debug;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (result.mainstay.artifacts) {
 | 
			
		||||
        outcome.artifacts = result.mainstay.artifacts;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return outcome;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exports.entryAsync = async function (value, schema, prefs) {
 | 
			
		||||
 | 
			
		||||
    let settings = Common.defaults;
 | 
			
		||||
    if (prefs) {
 | 
			
		||||
        settings = Common.preferences(Common.defaults, prefs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const result = internals.entry(value, schema, settings);
 | 
			
		||||
    const mainstay = result.mainstay;
 | 
			
		||||
    if (result.error) {
 | 
			
		||||
        if (mainstay.debug) {
 | 
			
		||||
            result.error.debug = mainstay.debug;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        throw result.error;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (mainstay.externals.length) {
 | 
			
		||||
        let root = result.value;
 | 
			
		||||
        const errors = [];
 | 
			
		||||
        for (const external of mainstay.externals) {
 | 
			
		||||
            const path = external.state.path;
 | 
			
		||||
            const linked = external.schema.type === 'link' ? mainstay.links.get(external.schema) : null;
 | 
			
		||||
            let node = root;
 | 
			
		||||
            let key;
 | 
			
		||||
            let parent;
 | 
			
		||||
 | 
			
		||||
            const ancestors = path.length ? [root] : [];
 | 
			
		||||
            const original = path.length ? Reach(value, path) : value;
 | 
			
		||||
 | 
			
		||||
            if (path.length) {
 | 
			
		||||
                key = path[path.length - 1];
 | 
			
		||||
 | 
			
		||||
                let current = root;
 | 
			
		||||
                for (const segment of path.slice(0, -1)) {
 | 
			
		||||
                    current = current[segment];
 | 
			
		||||
                    ancestors.unshift(current);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                parent = ancestors[0];
 | 
			
		||||
                node = parent[key];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                const createError = (code, local) => (linked || external.schema).$_createError(code, node, local, external.state, settings);
 | 
			
		||||
                const output = await external.method(node, {
 | 
			
		||||
                    schema: external.schema,
 | 
			
		||||
                    linked,
 | 
			
		||||
                    state: external.state,
 | 
			
		||||
                    prefs,
 | 
			
		||||
                    original,
 | 
			
		||||
                    error: createError,
 | 
			
		||||
                    errorsArray: internals.errorsArray,
 | 
			
		||||
                    warn: (code, local) => mainstay.warnings.push((linked || external.schema).$_createError(code, node, local, external.state, settings)),
 | 
			
		||||
                    message: (messages, local) => (linked || external.schema).$_createError('external', node, local, external.state, settings, { messages })
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                if (output === undefined ||
 | 
			
		||||
                    output === node) {
 | 
			
		||||
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (output instanceof Errors.Report) {
 | 
			
		||||
                    mainstay.tracer.log(external.schema, external.state, 'rule', 'external', 'error');
 | 
			
		||||
                    errors.push(output);
 | 
			
		||||
 | 
			
		||||
                    if (settings.abortEarly) {
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (Array.isArray(output) &&
 | 
			
		||||
                    output[Common.symbols.errors]) {
 | 
			
		||||
                    mainstay.tracer.log(external.schema, external.state, 'rule', 'external', 'error');
 | 
			
		||||
                    errors.push(...output);
 | 
			
		||||
 | 
			
		||||
                    if (settings.abortEarly) {
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (parent) {
 | 
			
		||||
                    mainstay.tracer.value(external.state, 'rule', node, output, 'external');
 | 
			
		||||
                    parent[key] = output;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    mainstay.tracer.value(external.state, 'rule', root, output, 'external');
 | 
			
		||||
                    root = output;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (err) {
 | 
			
		||||
                if (settings.errors.label) {
 | 
			
		||||
                    err.message += ` (${(external.label)})`;       // Change message to include path
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                throw err;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        result.value = root;
 | 
			
		||||
 | 
			
		||||
        if (errors.length) {
 | 
			
		||||
            result.error = Errors.process(errors, value, settings);
 | 
			
		||||
 | 
			
		||||
            if (mainstay.debug) {
 | 
			
		||||
                result.error.debug = mainstay.debug;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            throw result.error;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!settings.warnings &&
 | 
			
		||||
        !settings.debug &&
 | 
			
		||||
        !settings.artifacts) {
 | 
			
		||||
 | 
			
		||||
        return result.value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const outcome = { value: result.value };
 | 
			
		||||
    if (mainstay.warnings.length) {
 | 
			
		||||
        outcome.warning = Errors.details(mainstay.warnings);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (mainstay.debug) {
 | 
			
		||||
        outcome.debug = mainstay.debug;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (mainstay.artifacts) {
 | 
			
		||||
        outcome.artifacts = mainstay.artifacts;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return outcome;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.Mainstay = class {
 | 
			
		||||
 | 
			
		||||
    constructor(tracer, debug, links) {
 | 
			
		||||
 | 
			
		||||
        this.externals = [];
 | 
			
		||||
        this.warnings = [];
 | 
			
		||||
        this.tracer = tracer;
 | 
			
		||||
        this.debug = debug;
 | 
			
		||||
        this.links = links;
 | 
			
		||||
        this.shadow = null;
 | 
			
		||||
        this.artifacts = null;
 | 
			
		||||
 | 
			
		||||
        this._snapshots = [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    snapshot() {
 | 
			
		||||
 | 
			
		||||
        this._snapshots.push({
 | 
			
		||||
            externals: this.externals.slice(),
 | 
			
		||||
            warnings: this.warnings.slice()
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    restore() {
 | 
			
		||||
 | 
			
		||||
        const snapshot = this._snapshots.pop();
 | 
			
		||||
        this.externals = snapshot.externals;
 | 
			
		||||
        this.warnings = snapshot.warnings;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    commit() {
 | 
			
		||||
 | 
			
		||||
        this._snapshots.pop();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.entry = function (value, schema, prefs) {
 | 
			
		||||
 | 
			
		||||
    // Prepare state
 | 
			
		||||
 | 
			
		||||
    const { tracer, cleanup } = internals.tracer(schema, prefs);
 | 
			
		||||
    const debug = prefs.debug ? [] : null;
 | 
			
		||||
    const links = schema._ids._schemaChain ? new Map() : null;
 | 
			
		||||
    const mainstay = new internals.Mainstay(tracer, debug, links);
 | 
			
		||||
    const schemas = schema._ids._schemaChain ? [{ schema }] : null;
 | 
			
		||||
    const state = new State([], [], { mainstay, schemas });
 | 
			
		||||
 | 
			
		||||
    // Validate value
 | 
			
		||||
 | 
			
		||||
    const result = exports.validate(value, schema, state, prefs);
 | 
			
		||||
 | 
			
		||||
    // Process value and errors
 | 
			
		||||
 | 
			
		||||
    if (cleanup) {
 | 
			
		||||
        schema.$_root.untrace();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const error = Errors.process(result.errors, value, prefs);
 | 
			
		||||
    return { value: result.value, error, mainstay };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.tracer = function (schema, prefs) {
 | 
			
		||||
 | 
			
		||||
    if (schema.$_root._tracer) {
 | 
			
		||||
        return { tracer: schema.$_root._tracer._register(schema) };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (prefs.debug) {
 | 
			
		||||
        Assert(schema.$_root.trace, 'Debug mode not supported');
 | 
			
		||||
        return { tracer: schema.$_root.trace()._register(schema), cleanup: true };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return { tracer: internals.ignore };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exports.validate = function (value, schema, state, prefs, overrides = {}) {
 | 
			
		||||
 | 
			
		||||
    if (schema.$_terms.whens) {
 | 
			
		||||
        schema = schema._generate(value, state, prefs).schema;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Setup state and settings
 | 
			
		||||
 | 
			
		||||
    if (schema._preferences) {
 | 
			
		||||
        prefs = internals.prefs(schema, prefs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Cache
 | 
			
		||||
 | 
			
		||||
    if (schema._cache &&
 | 
			
		||||
        prefs.cache) {
 | 
			
		||||
 | 
			
		||||
        const result = schema._cache.get(value);
 | 
			
		||||
        state.mainstay.tracer.debug(state, 'validate', 'cached', !!result);
 | 
			
		||||
        if (result) {
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Helpers
 | 
			
		||||
 | 
			
		||||
    const createError = (code, local, localState) => schema.$_createError(code, value, local, localState || state, prefs);
 | 
			
		||||
    const helpers = {
 | 
			
		||||
        original: value,
 | 
			
		||||
        prefs,
 | 
			
		||||
        schema,
 | 
			
		||||
        state,
 | 
			
		||||
        error: createError,
 | 
			
		||||
        errorsArray: internals.errorsArray,
 | 
			
		||||
        warn: (code, local, localState) => state.mainstay.warnings.push(createError(code, local, localState)),
 | 
			
		||||
        message: (messages, local) => schema.$_createError('custom', value, local, state, prefs, { messages })
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Prepare
 | 
			
		||||
 | 
			
		||||
    state.mainstay.tracer.entry(schema, state);
 | 
			
		||||
 | 
			
		||||
    const def = schema._definition;
 | 
			
		||||
    if (def.prepare &&
 | 
			
		||||
        value !== undefined &&
 | 
			
		||||
        prefs.convert) {
 | 
			
		||||
 | 
			
		||||
        const prepared = def.prepare(value, helpers);
 | 
			
		||||
        if (prepared) {
 | 
			
		||||
            state.mainstay.tracer.value(state, 'prepare', value, prepared.value);
 | 
			
		||||
            if (prepared.errors) {
 | 
			
		||||
                return internals.finalize(prepared.value, [].concat(prepared.errors), helpers);         // Prepare error always aborts early
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            value = prepared.value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Type coercion
 | 
			
		||||
 | 
			
		||||
    if (def.coerce &&
 | 
			
		||||
        value !== undefined &&
 | 
			
		||||
        prefs.convert &&
 | 
			
		||||
        (!def.coerce.from || def.coerce.from.includes(typeof value))) {
 | 
			
		||||
 | 
			
		||||
        const coerced = def.coerce.method(value, helpers);
 | 
			
		||||
        if (coerced) {
 | 
			
		||||
            state.mainstay.tracer.value(state, 'coerced', value, coerced.value);
 | 
			
		||||
            if (coerced.errors) {
 | 
			
		||||
                return internals.finalize(coerced.value, [].concat(coerced.errors), helpers);           // Coerce error always aborts early
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            value = coerced.value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Empty value
 | 
			
		||||
 | 
			
		||||
    const empty = schema._flags.empty;
 | 
			
		||||
    if (empty &&
 | 
			
		||||
        empty.$_match(internals.trim(value, schema), state.nest(empty), Common.defaults)) {
 | 
			
		||||
 | 
			
		||||
        state.mainstay.tracer.value(state, 'empty', value, undefined);
 | 
			
		||||
        value = undefined;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Presence requirements (required, optional, forbidden)
 | 
			
		||||
 | 
			
		||||
    const presence = overrides.presence || schema._flags.presence || (schema._flags._endedSwitch ? null : prefs.presence);
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        if (presence === 'forbidden') {
 | 
			
		||||
            return internals.finalize(value, null, helpers);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (presence === 'required') {
 | 
			
		||||
            return internals.finalize(value, [schema.$_createError('any.required', value, null, state, prefs)], helpers);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (presence === 'optional') {
 | 
			
		||||
            if (schema._flags.default !== Common.symbols.deepDefault) {
 | 
			
		||||
                return internals.finalize(value, null, helpers);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            state.mainstay.tracer.value(state, 'default', value, {});
 | 
			
		||||
            value = {};
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else if (presence === 'forbidden') {
 | 
			
		||||
        return internals.finalize(value, [schema.$_createError('any.unknown', value, null, state, prefs)], helpers);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Allowed values
 | 
			
		||||
 | 
			
		||||
    const errors = [];
 | 
			
		||||
 | 
			
		||||
    if (schema._valids) {
 | 
			
		||||
        const match = schema._valids.get(value, state, prefs, schema._flags.insensitive);
 | 
			
		||||
        if (match) {
 | 
			
		||||
            if (prefs.convert) {
 | 
			
		||||
                state.mainstay.tracer.value(state, 'valids', value, match.value);
 | 
			
		||||
                value = match.value;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            state.mainstay.tracer.filter(schema, state, 'valid', match);
 | 
			
		||||
            return internals.finalize(value, null, helpers);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (schema._flags.only) {
 | 
			
		||||
            const report = schema.$_createError('any.only', value, { valids: schema._valids.values({ display: true }) }, state, prefs);
 | 
			
		||||
            if (prefs.abortEarly) {
 | 
			
		||||
                return internals.finalize(value, [report], helpers);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            errors.push(report);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Denied values
 | 
			
		||||
 | 
			
		||||
    if (schema._invalids) {
 | 
			
		||||
        const match = schema._invalids.get(value, state, prefs, schema._flags.insensitive);
 | 
			
		||||
        if (match) {
 | 
			
		||||
            state.mainstay.tracer.filter(schema, state, 'invalid', match);
 | 
			
		||||
            const report = schema.$_createError('any.invalid', value, { invalids: schema._invalids.values({ display: true }) }, state, prefs);
 | 
			
		||||
            if (prefs.abortEarly) {
 | 
			
		||||
                return internals.finalize(value, [report], helpers);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            errors.push(report);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Base type
 | 
			
		||||
 | 
			
		||||
    if (def.validate) {
 | 
			
		||||
        const base = def.validate(value, helpers);
 | 
			
		||||
        if (base) {
 | 
			
		||||
            state.mainstay.tracer.value(state, 'base', value, base.value);
 | 
			
		||||
            value = base.value;
 | 
			
		||||
 | 
			
		||||
            if (base.errors) {
 | 
			
		||||
                if (!Array.isArray(base.errors)) {
 | 
			
		||||
                    errors.push(base.errors);
 | 
			
		||||
                    return internals.finalize(value, errors, helpers);          // Base error always aborts early
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (base.errors.length) {
 | 
			
		||||
                    errors.push(...base.errors);
 | 
			
		||||
                    return internals.finalize(value, errors, helpers);          // Base error always aborts early
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Validate tests
 | 
			
		||||
 | 
			
		||||
    if (!schema._rules.length) {
 | 
			
		||||
        return internals.finalize(value, errors, helpers);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return internals.rules(value, errors, helpers);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.rules = function (value, errors, helpers) {
 | 
			
		||||
 | 
			
		||||
    const { schema, state, prefs } = helpers;
 | 
			
		||||
 | 
			
		||||
    for (const rule of schema._rules) {
 | 
			
		||||
        const definition = schema._definition.rules[rule.method];
 | 
			
		||||
 | 
			
		||||
        // Skip rules that are also applied in coerce step
 | 
			
		||||
 | 
			
		||||
        if (definition.convert &&
 | 
			
		||||
            prefs.convert) {
 | 
			
		||||
 | 
			
		||||
            state.mainstay.tracer.log(schema, state, 'rule', rule.name, 'full');
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Resolve references
 | 
			
		||||
 | 
			
		||||
        let ret;
 | 
			
		||||
        let args = rule.args;
 | 
			
		||||
        if (rule._resolve.length) {
 | 
			
		||||
            args = Object.assign({}, args);                                     // Shallow copy
 | 
			
		||||
            for (const key of rule._resolve) {
 | 
			
		||||
                const resolver = definition.argsByName.get(key);
 | 
			
		||||
 | 
			
		||||
                const resolved = args[key].resolve(value, state, prefs);
 | 
			
		||||
                const normalized = resolver.normalize ? resolver.normalize(resolved) : resolved;
 | 
			
		||||
 | 
			
		||||
                const invalid = Common.validateArg(normalized, null, resolver);
 | 
			
		||||
                if (invalid) {
 | 
			
		||||
                    ret = schema.$_createError('any.ref', resolved, { arg: key, ref: args[key], reason: invalid }, state, prefs);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                args[key] = normalized;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Test rule
 | 
			
		||||
 | 
			
		||||
        ret = ret || definition.validate(value, helpers, args, rule);           // Use ret if already set to reference error
 | 
			
		||||
 | 
			
		||||
        const result = internals.rule(ret, rule);
 | 
			
		||||
        if (result.errors) {
 | 
			
		||||
            state.mainstay.tracer.log(schema, state, 'rule', rule.name, 'error');
 | 
			
		||||
 | 
			
		||||
            if (rule.warn) {
 | 
			
		||||
                state.mainstay.warnings.push(...result.errors);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (prefs.abortEarly) {
 | 
			
		||||
                return internals.finalize(value, result.errors, helpers);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            errors.push(...result.errors);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            state.mainstay.tracer.log(schema, state, 'rule', rule.name, 'pass');
 | 
			
		||||
            state.mainstay.tracer.value(state, 'rule', value, result.value, rule.name);
 | 
			
		||||
            value = result.value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return internals.finalize(value, errors, helpers);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.rule = function (ret, rule) {
 | 
			
		||||
 | 
			
		||||
    if (ret instanceof Errors.Report) {
 | 
			
		||||
        internals.error(ret, rule);
 | 
			
		||||
        return { errors: [ret], value: null };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (Array.isArray(ret) &&
 | 
			
		||||
        ret[Common.symbols.errors]) {
 | 
			
		||||
 | 
			
		||||
        ret.forEach((report) => internals.error(report, rule));
 | 
			
		||||
        return { errors: ret, value: null };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return { errors: null, value: ret };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.error = function (report, rule) {
 | 
			
		||||
 | 
			
		||||
    if (rule.message) {
 | 
			
		||||
        report._setTemplate(rule.message);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return report;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.finalize = function (value, errors, helpers) {
 | 
			
		||||
 | 
			
		||||
    errors = errors || [];
 | 
			
		||||
    const { schema, state, prefs } = helpers;
 | 
			
		||||
 | 
			
		||||
    // Failover value
 | 
			
		||||
 | 
			
		||||
    if (errors.length) {
 | 
			
		||||
        const failover = internals.default('failover', undefined, errors, helpers);
 | 
			
		||||
        if (failover !== undefined) {
 | 
			
		||||
            state.mainstay.tracer.value(state, 'failover', value, failover);
 | 
			
		||||
            value = failover;
 | 
			
		||||
            errors = [];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Error override
 | 
			
		||||
 | 
			
		||||
    if (errors.length &&
 | 
			
		||||
        schema._flags.error) {
 | 
			
		||||
 | 
			
		||||
        if (typeof schema._flags.error === 'function') {
 | 
			
		||||
            errors = schema._flags.error(errors);
 | 
			
		||||
            if (!Array.isArray(errors)) {
 | 
			
		||||
                errors = [errors];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (const error of errors) {
 | 
			
		||||
                Assert(error instanceof Error || error instanceof Errors.Report, 'error() must return an Error object');
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            errors = [schema._flags.error];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Default
 | 
			
		||||
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        const defaulted = internals.default('default', value, errors, helpers);
 | 
			
		||||
        state.mainstay.tracer.value(state, 'default', value, defaulted);
 | 
			
		||||
        value = defaulted;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Cast
 | 
			
		||||
 | 
			
		||||
    if (schema._flags.cast &&
 | 
			
		||||
        value !== undefined) {
 | 
			
		||||
 | 
			
		||||
        const caster = schema._definition.cast[schema._flags.cast];
 | 
			
		||||
        if (caster.from(value)) {
 | 
			
		||||
            const casted = caster.to(value, helpers);
 | 
			
		||||
            state.mainstay.tracer.value(state, 'cast', value, casted, schema._flags.cast);
 | 
			
		||||
            value = casted;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Externals
 | 
			
		||||
 | 
			
		||||
    if (schema.$_terms.externals &&
 | 
			
		||||
        prefs.externals &&
 | 
			
		||||
        prefs._externals !== false) {                       // Disabled for matching
 | 
			
		||||
 | 
			
		||||
        for (const { method } of schema.$_terms.externals) {
 | 
			
		||||
            state.mainstay.externals.push({ method, schema, state, label: Errors.label(schema._flags, state, prefs) });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Result
 | 
			
		||||
 | 
			
		||||
    const result = { value, errors: errors.length ? errors : null };
 | 
			
		||||
 | 
			
		||||
    if (schema._flags.result) {
 | 
			
		||||
        result.value = schema._flags.result === 'strip' ? undefined : /* raw */ helpers.original;
 | 
			
		||||
        state.mainstay.tracer.value(state, schema._flags.result, value, result.value);
 | 
			
		||||
        state.shadow(value, schema._flags.result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Cache
 | 
			
		||||
 | 
			
		||||
    if (schema._cache &&
 | 
			
		||||
        prefs.cache !== false &&
 | 
			
		||||
        !schema._refs.length) {
 | 
			
		||||
 | 
			
		||||
        schema._cache.set(helpers.original, result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Artifacts
 | 
			
		||||
 | 
			
		||||
    if (value !== undefined &&
 | 
			
		||||
        !result.errors &&
 | 
			
		||||
        schema._flags.artifact !== undefined) {
 | 
			
		||||
 | 
			
		||||
        state.mainstay.artifacts = state.mainstay.artifacts || new Map();
 | 
			
		||||
        if (!state.mainstay.artifacts.has(schema._flags.artifact)) {
 | 
			
		||||
            state.mainstay.artifacts.set(schema._flags.artifact, []);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        state.mainstay.artifacts.get(schema._flags.artifact).push(state.path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.prefs = function (schema, prefs) {
 | 
			
		||||
 | 
			
		||||
    const isDefaultOptions = prefs === Common.defaults;
 | 
			
		||||
    if (isDefaultOptions &&
 | 
			
		||||
        schema._preferences[Common.symbols.prefs]) {
 | 
			
		||||
 | 
			
		||||
        return schema._preferences[Common.symbols.prefs];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    prefs = Common.preferences(prefs, schema._preferences);
 | 
			
		||||
    if (isDefaultOptions) {
 | 
			
		||||
        schema._preferences[Common.symbols.prefs] = prefs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return prefs;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.default = function (flag, value, errors, helpers) {
 | 
			
		||||
 | 
			
		||||
    const { schema, state, prefs } = helpers;
 | 
			
		||||
    const source = schema._flags[flag];
 | 
			
		||||
    if (prefs.noDefaults ||
 | 
			
		||||
        source === undefined) {
 | 
			
		||||
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    state.mainstay.tracer.log(schema, state, 'rule', flag, 'full');
 | 
			
		||||
 | 
			
		||||
    if (!source) {
 | 
			
		||||
        return source;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (typeof source === 'function') {
 | 
			
		||||
        const args = source.length ? [Clone(state.ancestors[0]), helpers] : [];
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            return source(...args);
 | 
			
		||||
        }
 | 
			
		||||
        catch (err) {
 | 
			
		||||
            errors.push(schema.$_createError(`any.${flag}`, null, { error: err }, state, prefs));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (typeof source !== 'object') {
 | 
			
		||||
        return source;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (source[Common.symbols.literal]) {
 | 
			
		||||
        return source.literal;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (Common.isResolvable(source)) {
 | 
			
		||||
        return source.resolve(value, state, prefs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Clone(source);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.trim = function (value, schema) {
 | 
			
		||||
 | 
			
		||||
    if (typeof value !== 'string') {
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const trim = schema.$_getRule('trim');
 | 
			
		||||
    if (!trim ||
 | 
			
		||||
        !trim.args.enabled) {
 | 
			
		||||
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return value.trim();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.ignore = {
 | 
			
		||||
    active: false,
 | 
			
		||||
    debug: Ignore,
 | 
			
		||||
    entry: Ignore,
 | 
			
		||||
    filter: Ignore,
 | 
			
		||||
    log: Ignore,
 | 
			
		||||
    resolve: Ignore,
 | 
			
		||||
    value: Ignore
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.errorsArray = function () {
 | 
			
		||||
 | 
			
		||||
    const errors = [];
 | 
			
		||||
    errors[Common.symbols.errors] = true;
 | 
			
		||||
    return errors;
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user