.
This commit is contained in:
		
							
								
								
									
										414
									
								
								qwen/nodejs/node_modules/joi/lib/ref.js
									
									
									
										generated
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										414
									
								
								qwen/nodejs/node_modules/joi/lib/ref.js
									
									
									
										generated
									
									
										vendored
									
									
										Executable file
									
								
							@@ -0,0 +1,414 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
const Assert = require('@hapi/hoek/lib/assert');
 | 
			
		||||
const Clone = require('@hapi/hoek/lib/clone');
 | 
			
		||||
const Reach = require('@hapi/hoek/lib/reach');
 | 
			
		||||
 | 
			
		||||
const Common = require('./common');
 | 
			
		||||
 | 
			
		||||
let Template;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const internals = {
 | 
			
		||||
    symbol: Symbol('ref'),      // Used to internally identify references (shared with other joi versions)
 | 
			
		||||
    defaults: {
 | 
			
		||||
        adjust: null,
 | 
			
		||||
        in: false,
 | 
			
		||||
        iterables: null,
 | 
			
		||||
        map: null,
 | 
			
		||||
        separator: '.',
 | 
			
		||||
        type: 'value'
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exports.create = function (key, options = {}) {
 | 
			
		||||
 | 
			
		||||
    Assert(typeof key === 'string', 'Invalid reference key:', key);
 | 
			
		||||
    Common.assertOptions(options, ['adjust', 'ancestor', 'in', 'iterables', 'map', 'prefix', 'render', 'separator']);
 | 
			
		||||
    Assert(!options.prefix || typeof options.prefix === 'object', 'options.prefix must be of type object');
 | 
			
		||||
 | 
			
		||||
    const ref = Object.assign({}, internals.defaults, options);
 | 
			
		||||
    delete ref.prefix;
 | 
			
		||||
 | 
			
		||||
    const separator = ref.separator;
 | 
			
		||||
    const context = internals.context(key, separator, options.prefix);
 | 
			
		||||
    ref.type = context.type;
 | 
			
		||||
    key = context.key;
 | 
			
		||||
 | 
			
		||||
    if (ref.type === 'value') {
 | 
			
		||||
        if (context.root) {
 | 
			
		||||
            Assert(!separator || key[0] !== separator, 'Cannot specify relative path with root prefix');
 | 
			
		||||
            ref.ancestor = 'root';
 | 
			
		||||
            if (!key) {
 | 
			
		||||
                key = null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (separator &&
 | 
			
		||||
            separator === key) {
 | 
			
		||||
 | 
			
		||||
            key = null;
 | 
			
		||||
            ref.ancestor = 0;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            if (ref.ancestor !== undefined) {
 | 
			
		||||
                Assert(!separator || !key || key[0] !== separator, 'Cannot combine prefix with ancestor option');
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                const [ancestor, slice] = internals.ancestor(key, separator);
 | 
			
		||||
                if (slice) {
 | 
			
		||||
                    key = key.slice(slice);
 | 
			
		||||
                    if (key === '') {
 | 
			
		||||
                        key = null;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ref.ancestor = ancestor;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ref.path = separator ? (key === null ? [] : key.split(separator)) : [key];
 | 
			
		||||
 | 
			
		||||
    return new internals.Ref(ref);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exports.in = function (key, options = {}) {
 | 
			
		||||
 | 
			
		||||
    return exports.create(key, { ...options, in: true });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exports.isRef = function (ref) {
 | 
			
		||||
 | 
			
		||||
    return ref ? !!ref[Common.symbols.ref] : false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.Ref = class {
 | 
			
		||||
 | 
			
		||||
    constructor(options) {
 | 
			
		||||
 | 
			
		||||
        Assert(typeof options === 'object', 'Invalid reference construction');
 | 
			
		||||
        Common.assertOptions(options, [
 | 
			
		||||
            'adjust', 'ancestor', 'in', 'iterables', 'map', 'path', 'render', 'separator', 'type',  // Copied
 | 
			
		||||
            'depth', 'key', 'root', 'display'                                                       // Overridden
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        Assert([false, undefined].includes(options.separator) || typeof options.separator === 'string' && options.separator.length === 1, 'Invalid separator');
 | 
			
		||||
        Assert(!options.adjust || typeof options.adjust === 'function', 'options.adjust must be a function');
 | 
			
		||||
        Assert(!options.map || Array.isArray(options.map), 'options.map must be an array');
 | 
			
		||||
        Assert(!options.map || !options.adjust, 'Cannot set both map and adjust options');
 | 
			
		||||
 | 
			
		||||
        Object.assign(this, internals.defaults, options);
 | 
			
		||||
 | 
			
		||||
        Assert(this.type === 'value' || this.ancestor === undefined, 'Non-value references cannot reference ancestors');
 | 
			
		||||
 | 
			
		||||
        if (Array.isArray(this.map)) {
 | 
			
		||||
            this.map = new Map(this.map);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.depth = this.path.length;
 | 
			
		||||
        this.key = this.path.length ? this.path.join(this.separator) : null;
 | 
			
		||||
        this.root = this.path[0];
 | 
			
		||||
 | 
			
		||||
        this.updateDisplay();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    resolve(value, state, prefs, local, options = {}) {
 | 
			
		||||
 | 
			
		||||
        Assert(!this.in || options.in, 'Invalid in() reference usage');
 | 
			
		||||
 | 
			
		||||
        if (this.type === 'global') {
 | 
			
		||||
            return this._resolve(prefs.context, state, options);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.type === 'local') {
 | 
			
		||||
            return this._resolve(local, state, options);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this.ancestor) {
 | 
			
		||||
            return this._resolve(value, state, options);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.ancestor === 'root') {
 | 
			
		||||
            return this._resolve(state.ancestors[state.ancestors.length - 1], state, options);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Assert(this.ancestor <= state.ancestors.length, 'Invalid reference exceeds the schema root:', this.display);
 | 
			
		||||
        return this._resolve(state.ancestors[this.ancestor - 1], state, options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _resolve(target, state, options) {
 | 
			
		||||
 | 
			
		||||
        let resolved;
 | 
			
		||||
 | 
			
		||||
        if (this.type === 'value' &&
 | 
			
		||||
            state.mainstay.shadow &&
 | 
			
		||||
            options.shadow !== false) {
 | 
			
		||||
 | 
			
		||||
            resolved = state.mainstay.shadow.get(this.absolute(state));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (resolved === undefined) {
 | 
			
		||||
            resolved = Reach(target, this.path, { iterables: this.iterables, functions: true });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.adjust) {
 | 
			
		||||
            resolved = this.adjust(resolved);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.map) {
 | 
			
		||||
            const mapped = this.map.get(resolved);
 | 
			
		||||
            if (mapped !== undefined) {
 | 
			
		||||
                resolved = mapped;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (state.mainstay) {
 | 
			
		||||
            state.mainstay.tracer.resolve(state, this, resolved);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return resolved;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    toString() {
 | 
			
		||||
 | 
			
		||||
        return this.display;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    absolute(state) {
 | 
			
		||||
 | 
			
		||||
        return [...state.path.slice(0, -this.ancestor), ...this.path];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    clone() {
 | 
			
		||||
 | 
			
		||||
        return new internals.Ref(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    describe() {
 | 
			
		||||
 | 
			
		||||
        const ref = { path: this.path };
 | 
			
		||||
 | 
			
		||||
        if (this.type !== 'value') {
 | 
			
		||||
            ref.type = this.type;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.separator !== '.') {
 | 
			
		||||
            ref.separator = this.separator;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.type === 'value' &&
 | 
			
		||||
            this.ancestor !== 1) {
 | 
			
		||||
 | 
			
		||||
            ref.ancestor = this.ancestor;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.map) {
 | 
			
		||||
            ref.map = [...this.map];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (const key of ['adjust', 'iterables', 'render']) {
 | 
			
		||||
            if (this[key] !== null &&
 | 
			
		||||
                this[key] !== undefined) {
 | 
			
		||||
 | 
			
		||||
                ref[key] = this[key];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.in !== false) {
 | 
			
		||||
            ref.in = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return { ref };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    updateDisplay() {
 | 
			
		||||
 | 
			
		||||
        const key = this.key !== null ? this.key : '';
 | 
			
		||||
        if (this.type !== 'value') {
 | 
			
		||||
            this.display = `ref:${this.type}:${key}`;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this.separator) {
 | 
			
		||||
            this.display = `ref:${key}`;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this.ancestor) {
 | 
			
		||||
            this.display = `ref:${this.separator}${key}`;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.ancestor === 'root') {
 | 
			
		||||
            this.display = `ref:root:${key}`;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.ancestor === 1) {
 | 
			
		||||
            this.display = `ref:${key || '..'}`;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const lead = new Array(this.ancestor + 1).fill(this.separator).join('');
 | 
			
		||||
        this.display = `ref:${lead}${key || ''}`;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.Ref.prototype[Common.symbols.ref] = true;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exports.build = function (desc) {
 | 
			
		||||
 | 
			
		||||
    desc = Object.assign({}, internals.defaults, desc);
 | 
			
		||||
    if (desc.type === 'value' &&
 | 
			
		||||
        desc.ancestor === undefined) {
 | 
			
		||||
 | 
			
		||||
        desc.ancestor = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return new internals.Ref(desc);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.context = function (key, separator, prefix = {}) {
 | 
			
		||||
 | 
			
		||||
    key = key.trim();
 | 
			
		||||
 | 
			
		||||
    if (prefix) {
 | 
			
		||||
        const globalp = prefix.global === undefined ? '$' : prefix.global;
 | 
			
		||||
        if (globalp !== separator &&
 | 
			
		||||
            key.startsWith(globalp)) {
 | 
			
		||||
 | 
			
		||||
            return { key: key.slice(globalp.length), type: 'global' };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const local = prefix.local === undefined ? '#' : prefix.local;
 | 
			
		||||
        if (local !== separator &&
 | 
			
		||||
            key.startsWith(local)) {
 | 
			
		||||
 | 
			
		||||
            return { key: key.slice(local.length), type: 'local' };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const root = prefix.root === undefined ? '/' : prefix.root;
 | 
			
		||||
        if (root !== separator &&
 | 
			
		||||
            key.startsWith(root)) {
 | 
			
		||||
 | 
			
		||||
            return { key: key.slice(root.length), type: 'value', root: true };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return { key, type: 'value' };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
internals.ancestor = function (key, separator) {
 | 
			
		||||
 | 
			
		||||
    if (!separator) {
 | 
			
		||||
        return [1, 0];              // 'a_b' -> 1 (parent)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (key[0] !== separator) {     // 'a.b' -> 1 (parent)
 | 
			
		||||
        return [1, 0];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (key[1] !== separator) {     // '.a.b' -> 0 (self)
 | 
			
		||||
        return [0, 1];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let i = 2;
 | 
			
		||||
    while (key[i] === separator) {
 | 
			
		||||
        ++i;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return [i - 1, i];              // '...a.b.' -> 2 (grandparent)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exports.toSibling = 0;
 | 
			
		||||
 | 
			
		||||
exports.toParent = 1;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exports.Manager = class {
 | 
			
		||||
 | 
			
		||||
    constructor() {
 | 
			
		||||
 | 
			
		||||
        this.refs = [];                     // 0: [self refs], 1: [parent refs], 2: [grandparent refs], ...
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    register(source, target) {
 | 
			
		||||
 | 
			
		||||
        if (!source) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        target = target === undefined ? exports.toParent : target;
 | 
			
		||||
 | 
			
		||||
        // Array
 | 
			
		||||
 | 
			
		||||
        if (Array.isArray(source)) {
 | 
			
		||||
            for (const ref of source) {
 | 
			
		||||
                this.register(ref, target);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Schema
 | 
			
		||||
 | 
			
		||||
        if (Common.isSchema(source)) {
 | 
			
		||||
            for (const item of source._refs.refs) {
 | 
			
		||||
                if (item.ancestor - target >= 0) {
 | 
			
		||||
                    this.refs.push({ ancestor: item.ancestor - target, root: item.root });
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Reference
 | 
			
		||||
 | 
			
		||||
        if (exports.isRef(source) &&
 | 
			
		||||
            source.type === 'value' &&
 | 
			
		||||
            source.ancestor - target >= 0) {
 | 
			
		||||
 | 
			
		||||
            this.refs.push({ ancestor: source.ancestor - target, root: source.root });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Template
 | 
			
		||||
 | 
			
		||||
        Template = Template || require('./template');
 | 
			
		||||
 | 
			
		||||
        if (Template.isTemplate(source)) {
 | 
			
		||||
            this.register(source.refs(), target);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get length() {
 | 
			
		||||
 | 
			
		||||
        return this.refs.length;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    clone() {
 | 
			
		||||
 | 
			
		||||
        const copy = new exports.Manager();
 | 
			
		||||
        copy.refs = Clone(this.refs);
 | 
			
		||||
        return copy;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    reset() {
 | 
			
		||||
 | 
			
		||||
        this.refs = [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    roots() {
 | 
			
		||||
 | 
			
		||||
        return this.refs.filter((ref) => !ref.ancestor).map((ref) => ref.root);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user