UNPKG

mage-validator

Version:

Validation utility for MAGE user commands & topics (TypeScript)

280 lines 33.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const ValidatedTopic_1 = require("./ValidatedTopic"); const storage_1 = require("class-transformer/storage"); const classTransformer = require("class-transformer"); const mage = require("mage"); const util_1 = require("util"); const { Tome, ObjectTome, ArrayTome } = mage.require('tomes'); const ARRAY_GET_METHODS = [ 'pop', 'shift' ]; const ARRAY_SLICE_METHODS = [ 'slice', 'splice' ]; const ARRAY_PARSE_METHODS = [ 'sort', 'forEach', 'filter', 'map', 'every', 'some', 'reduce', 'reduceRight', 'find', 'findIndex' ]; const ARRAY_SEARCH_METHODS = [ 'includes' ]; function createToString(tome) { return () => JSON.stringify(Tome.unTome(tome)); } function createInspect(tome, className) { return (depth = 1, options = {}) => { options.depth = depth; return className + ' -> ' + util_1.inspect(Tome.unTome(tome), options); }; } function proxifyOrUntome(t, ctor) { if (ObjectTome.isObjectTome(t) || ArrayTome.isArrayTome(t)) { return createTomeProxy(t, ctor); } return t.valueOf(); } function processArrayTomeMethodRequest(target, key, ctor) { // Entries iterator if (key === 'entries') { return target .map((t) => proxifyOrUntome(t, ctor)) .entries; } // For pop, shift, etc if (ARRAY_GET_METHODS.includes(key)) { return (...args) => proxifyOrUntome(target[key](...args), ctor); } // For slice, splice, etc if (ARRAY_SLICE_METHODS.includes(key)) { return (...args) => target[key](...args) .map((val) => proxifyOrUntome(val, ctor)); } if (ARRAY_SEARCH_METHODS.includes(key)) { return function (...args) { const vals = target.map((t) => proxifyOrUntome(t, ctor)); return vals[key](...args); }; } // For methods receiving a function as a first parameter (map, reduce, forEach, etc) if (ARRAY_PARSE_METHODS.includes(key)) { return function (...args) { const iterator = args[0]; args[0] = function (...iteratorArgs) { iteratorArgs = iteratorArgs.map((t) => proxifyOrUntome(t, ctor)); return iterator(...iteratorArgs); }; const ret = target[key](...args); if (key === 'find') { return ret ? proxifyOrUntome(ret, ctor) : ret; } if (key === 'filter') { return ret.map((t) => proxifyOrUntome(t, ctor)); } return ret; }; } // All other methods must be bound to the target return target[key].bind(target); } function extractType(typeInfo, typeMap, key) { if (typeInfo) { return typeInfo.typeFunction(); } if (typeMap[key]) { return typeMap[key]; } return Object; } /** * Wrap tome and sub-tome instances intp proxies, allowing * for direct access to attributes */ function createTomeProxy(tome, ctor) { const typeMap = {}; const proxy = new Proxy(tome, { ownKeys(target) { return Object.keys(target).concat([ '__dirty__', '__root__', '__diff__', '__diffEnabled__', '__version__', '__parent__', '__key__' ]); }, getPrototypeOf(target) { if (ArrayTome.isArrayTome(target)) { return Array.prototype; } /* istanbul ignore next */ return ctor.prototype || Object.prototype; }, get(target, key) { // Return a stringified object/array/etc if (key === 'toString' || key === Symbol.toStringTag) { return createToString(target); } // the type definition for util.inspect.custom seems to be missing if (key === 'inspect' || key === util_1.inspect.custom) { let name; if (ArrayTome.isArrayTome(target)) { name = 'Array'; } else { name = ctor.name; } return createInspect(target, name); } // Return the data structure's standard iterator if (key === Symbol.iterator) { /* istanbul ignore else */ if (ArrayTome.isArrayTome(target)) { return target .valueOf() .map((t) => proxifyOrUntome(t, ctor))[Symbol.iterator]; } /* istanbul ignore next*/ return target[Symbol.iterator]; } // Return the correct constructor - we want // ArrayTomes to appear as being Arrays, // and everything else as the known type if (key === 'constructor') { if (ArrayTome.isArrayTome(target)) { return Array; } return ctor; } // Extract the value const val = target[key]; // Undefined means either the value is undefined, // or we are trying to access a prototype method if (val === undefined) { if (ctor.prototype[key]) { return ctor.prototype[key].bind(proxy); } return val; } // Create a ObjectTome or ArrayTome proxy if (ObjectTome.isObjectTome(val) || ArrayTome.isArrayTome(val)) { if (ArrayTome.isArrayTome(target)) { return createTomeProxy(val, ctor); } const typeInfo = storage_1.defaultMetadataStorage.findTypeMetadata(ctor, key); const childCtor = extractType(typeInfo, typeMap, key); return createTomeProxy(target[key], childCtor); } // Mangle array functions so that they keep the proper // context and proxy siblings when needed if (typeof val === 'function' && ArrayTome.isArrayTome(target)) { return processArrayTomeMethodRequest(target, key, ctor); } // TODO: map object method calls to their "real" prototype // In all other cases, return the underlying value of the attribute return val.valueOf(); }, set(target, key, value) { target.set(key, value); typeMap[key] = undefined; if (value !== undefined && value !== null) { typeMap[key] = value.constructor; } return true; }, deleteProperty(_target, key) { tome.del(key); return true; } }); return proxy; } /** * Dealing with tome topics */ class ValidatedTomeTopic extends ValidatedTopic_1.default { static async create(state, index, data) { const className = this.getClassName(); const typeMap = {}; const isTome = Tome.isTome(data); const rawData = isTome ? Tome.unTome(data) : data; const instance = classTransformer.plainToClass(this, rawData) || new this(); const tome = isTome ? data : Tome.conjure(instance); instance.setTopic(className); instance.setState(state); await instance.setIndex(index); const proxy = new Proxy(instance, { ownKeys() { return Object.keys(tome); }, getOwnPropertyDescriptor(target, key) { return { configurable: true, enumerable: true, value: this.get(target, key) }; }, get(target, key) { if (key === 'toString' || key === Symbol.toStringTag) { return createToString(tome); } // the type definition for util.inspect.custom seems to be missing if (key === 'inspect' || key === util_1.inspect.custom) { return createInspect(tome, className); } /* istanbul ignore next */ if (key === 'set' || key === 'del') { return target[key]; } if (key === 'constructor') { return target.constructor; } if (key === 'getData') { return () => tome; } if (!tome[key]) { if (typeof target[key] === 'function') { return target[key].bind(proxy); } if (key === '_state' || key === '_topic' || key === '_index') { return target[key]; } return undefined; } if (ObjectTome.isObjectTome(tome[key]) || ArrayTome.isArrayTome(tome[key])) { const typeInfo = storage_1.defaultMetadataStorage.findTypeMetadata(target.constructor, key); const ctor = extractType(typeInfo, typeMap, key); return createTomeProxy(tome[key], ctor); } return tome[key].valueOf(); }, set(_target, key, value) { tome.set(key, value); typeMap[key] = undefined; if (value !== undefined && value !== null) { typeMap[key] = value.constructor; } return true; }, deleteProperty(target, key) { const val = tome[key]; if (Tome.isTome(val)) { tome.del(key); } delete target[key]; return true; } }); return proxy; } } ValidatedTomeTopic.mediaType = 'application/x-tome'; exports.default = ValidatedTomeTopic; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVmFsaWRhdGVkVG9tZVRvcGljLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsYXNzZXMvVmFsaWRhdGVkVG9tZVRvcGljLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEscURBQXlFO0FBQ3pFLHVEQUFrRTtBQUNsRSxzREFBcUQ7QUFHckQsNkJBQTRCO0FBRTVCLCtCQUE4QjtBQUU5QixNQUFNLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0FBRTdELE1BQU0saUJBQWlCLEdBQUc7SUFDeEIsS0FBSztJQUNMLE9BQU87Q0FDUixDQUFBO0FBRUQsTUFBTSxtQkFBbUIsR0FBRztJQUMxQixPQUFPO0lBQ1AsUUFBUTtDQUNULENBQUE7QUFFRCxNQUFNLG1CQUFtQixHQUFHO0lBQzFCLE1BQU07SUFDTixTQUFTO0lBQ1QsUUFBUTtJQUNSLEtBQUs7SUFDTCxPQUFPO0lBQ1AsTUFBTTtJQUNOLFFBQVE7SUFDUixhQUFhO0lBQ2IsTUFBTTtJQUNOLFdBQVc7Q0FDWixDQUFBO0FBRUQsTUFBTSxvQkFBb0IsR0FBRztJQUMzQixVQUFVO0NBQ1gsQ0FBQTtBQUVELHdCQUF3QixJQUFTO0lBQy9CLE9BQU8sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUE7QUFDaEQsQ0FBQztBQUVELHVCQUF1QixJQUFTLEVBQUUsU0FBaUI7SUFDakQsT0FBTyxDQUFDLFFBQWdCLENBQUMsRUFBRSxVQUFlLEVBQUUsRUFBRSxFQUFFO1FBQzlDLE9BQU8sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFBO1FBQ3JCLE9BQU8sU0FBUyxHQUFHLE1BQU0sR0FBRyxjQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQTtJQUNqRSxD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QUFNLEVBQUUsR0FBRztnQkFDeEIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUVyQixJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUU7b0JBQ3BCLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7aUJBQ2Q7Z0JBRUQsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7Z0JBRWxCLE9BQU8sSUFBSSxDQUFBO1lBQ2IsQ0FBQztTQUNGLENBQUMsQ0FBQTtRQUVGLE9BQU8sS0FBSyxDQUFBO0lBQ2QsQ0FBQzs7QUFsR3NCLDRCQUFTLEdBQUcsb0JBQW9CLENBQUE7QUFEekQscUNBb0dDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFZhbGlkYXRlZFRvcGljLCB7IElTdGF0aWNUaGlzLCBUb3BpY0RhdGEgfSBmcm9tICcuL1ZhbGlkYXRlZFRvcGljJ1xuaW1wb3J0IHsgZGVmYXVsdE1ldGFkYXRhU3RvcmFnZSB9IGZyb20gJ2NsYXNzLXRyYW5zZm9ybWVyL3N0b3JhZ2UnXG5pbXBvcnQgKiBhcyBjbGFzc1RyYW5zZm9ybWVyIGZyb20gJ2NsYXNzLXRyYW5zZm9ybWVyJ1xuXG5pbXBvcnQgeyBhcmNoaXZpc3QgfSBmcm9tICdtYWdlJ1xuaW1wb3J0ICogYXMgbWFnZSBmcm9tICdtYWdlJ1xuXG5pbXBvcnQgeyBpbnNwZWN0IH0gZnJvbSAndXRpbCdcblxuY29uc3QgeyBUb21lLCBPYmplY3RUb21lLCBBcnJheVRvbWUgfSA9IG1hZ2UucmVxdWlyZSgndG9tZXMnKVxuXG5jb25zdCBBUlJBWV9HRVRfTUVUSE9EUyA9IFtcbiAgJ3BvcCcsXG4gICdzaGlmdCdcbl1cblxuY29uc3QgQVJSQVlfU0xJQ0VfTUVUSE9EUyA9IFtcbiAgJ3NsaWNlJyxcbiAgJ3NwbGljZSdcbl1cblxuY29uc3QgQVJSQVlfUEFSU0VfTUVUSE9EUyA9IFtcbiAgJ3NvcnQnLFxuICAnZm9yRWFjaCcsXG4gICdmaWx0ZXInLFxuICAnbWFwJyxcbiAgJ2V2ZXJ5JyxcbiAgJ3NvbWUnLFxuICAncmVkdWNlJyxcbiAgJ3JlZHVjZVJpZ2h0JyxcbiAgJ2ZpbmQnLFxuICAnZmluZEluZGV4J1xuXVxuXG5jb25zdCBBUlJBWV9TRUFSQ0hfTUVUSE9EUyA9IFtcbiAgJ2luY2x1ZGVzJ1xuXVxuXG5mdW5jdGlvbiBjcmVhdGVUb1N0cmluZyh0b21lOiBhbnkpIHtcbiAgcmV0dXJuICgpID0+IEpTT04uc3RyaW5naWZ5KFRvbWUudW5Ub21lKHRvbWUpKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVJbnNwZWN0KHRvbWU6IGFueSwgY2xhc3NOYW1lOiBzdHJpbmcpIHtcbiAgcmV0dXJuIChkZXB0aDogbnVtYmVyID0gMSwgb3B0aW9uczogYW55ID0ge30pID0+IHtcbiAgICBvcHRpb25zLmRlcHRoID0gZGVwdGhcbiAgICByZXR1cm4gY2xhc3NOYW1lICsgJyAtPiAnICsgaW5zcGVjdChUb21lLnVuVG9tZSh0b21lKSwgb3B0aW9ucylcbiAgfVxufVxuXG5mdW5jdGlvbiBwcm94aWZ5T3JVbnRvbWUodDogYW55LCBjdG9yOiBhbnkpIHtcbiAgaWYgKE9iamVjdFRvbWUuaXNPYmplY3RUb21lKHQpIHx8IEFycmF5VG9tZS5pc0FycmF5VG9tZSh0KSApIHtcbiAgICByZXR1cm4gY3JlYXRlVG9tZVByb3h5KHQsIGN0b3IpXG4gIH1cblxuICByZXR1cm4gdC52YWx1ZU9mKClcbn1cblxuZnVuY3Rpb24gcHJvY2Vzc0FycmF5VG9tZU1ldGhvZFJlcXVlc3QodGFyZ2V0OiBhbnksIGtleTogc3RyaW5nLCBjdG9yOiBhbnkpIHtcbiAgLy8gRW50cmllcyBpdGVyYXRvclxuICBpZiAoa2V5ID09PSAnZW50cmllcycpIHtcbiAgICByZXR1cm4gdGFyZ2V0XG4gICAgICAubWFwKCh0OiBhbnkpID0+IHByb3hpZnlPclVudG9tZSh0LCBjdG9yKSlcbiAgICAgIC5lbnRyaWVzXG4gIH1cblxuICAvLyBGb3IgcG9wLCBzaGlmdCwgZXRjXG4gIGlmIChBUlJBWV9HRVRfTUVUSE9EUy5pbmNsdWRlcyhrZXkpKSB7XG4gICAgcmV0dXJuICguLi5hcmdzOiBhbnlbXSkgPT4gcHJveGlmeU9yVW50b21lKHRhcmdldFtrZXldKC4uLmFyZ3MpLCBjdG9yKVxuICB9XG5cbiAgLy8gRm9yIHNsaWNlLCBzcGxpY2UsIGV0Y1xuICBpZiAoQVJSQVlfU0xJQ0VfTUVUSE9EUy5pbmNsdWRlcyhrZXkpKSB7XG4gICAgcmV0dXJuICguLi5hcmdzOiBhbnlbXSkgPT4gdGFyZ2V0W2tleV0oLi4uYXJncylcbiAgICAgIC5tYXAoKHZhbDogYW55KSA9PiBwcm94aWZ5T3JVbnRvbWUodmFsLCBjdG9yKSlcbiAgfVxuXG4gIGlmIChBUlJBWV9TRUFSQ0hfTUVUSE9EUy5pbmNsdWRlcyhrZXkpKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzOiBhbnlbXSkge1xuICAgICAgY29uc3QgdmFscyA9IHRhcmdldC5tYXAoKHQ6IGFueSkgPT4gcHJveGlmeU9yVW50b21lKHQsIGN0b3IpKVxuXG4gICAgICByZXR1cm4gdmFsc1trZXldKC4uLmFyZ3MpXG4gICAgfVxuICB9XG5cbiAgLy8gRm9yIG1ldGhvZHMgcmVjZWl2aW5nIGEgZnVuY3Rpb24gYXMgYSBmaXJzdCBwYXJhbWV0ZXIgKG1hcCwgcmVkdWNlLCBmb3JFYWNoLCBldGMpXG4gIGlmIChBUlJBWV9QQVJTRV9NRVRIT0RTLmluY2x1ZGVzKGtleSkpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgICBjb25zdCBpdGVyYXRvciA9IGFyZ3NbMF1cbiAgICAgIGFyZ3NbMF0gPSBmdW5jdGlvbiAoLi4uaXRlcmF0b3JBcmdzOiBhbnlbXSkge1xuICAgICAgICBpdGVyYXRvckFyZ3MgPSBpdGVyYXRvckFyZ3MubWFwKCh0OiBhbnkpID0+IHByb3hpZnlPclVudG9tZSh0LCBjdG9yKSlcblxuICAgICAgICByZXR1cm4gaXRlcmF0b3IoLi4uaXRlcmF0b3JBcmdzKVxuICAgICAgfVxuXG4gICAgICBjb25zdCByZXQgPSB0YXJnZXRba2V5XSguLi5hcmdzKVxuXG4gICAgICBpZiAoa2V5ID09PSAnZmluZCcpIHtcbiAgICAgICAgcmV0dXJuIHJldCA/IHByb3hpZnlPclVudG9tZShyZXQsIGN0b3IpIDogcmV0XG4gICAgICB9XG5cbiAgICAgIGlmIChrZXkgPT09ICdmaWx0ZXInKSB7XG4gICAgICAgIHJldHVybiByZXQubWFwKCh0OiBhbnkpID0+IHByb3hpZnlPclVudG9tZSh0LCBjdG9yKSlcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJldFxuICAgIH1cbiAgfVxuXG4gIC8vIEFsbCBvdGhlciBtZXRob2RzIG11c3QgYmUgYm91bmQgdG8gdGhlIHRhcmdldFxuICByZXR1cm4gdGFyZ2V0W2tleV0uYmluZCh0YXJnZXQpXG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RUeXBlKHR5cGVJbmZvOiBhbnksIHR5cGVNYXA6IGFueSwga2V5OiBhbnkpIHtcbiAgaWYgKHR5cGVJbmZvKSB7XG4gICAgcmV0dXJuIHR5cGVJbmZvLnR5cGVGdW5jdGlvbigpXG4gIH1cblxuICBpZiAodHlwZU1hcFtrZXldKSB7XG4gICAgcmV0dXJuIHR5cGVNYXBba2V5XVxuICB9XG5cbiAgcmV0dXJuIE9iamVjdFxufVxuXG4vKipcbiAqIFdyYXAgdG9tZSBhbmQgc3ViLXRvbWUgaW5zdGFuY2VzIGludHAgcHJveGllcywgYWxsb3dpbmdcbiAqIGZvciBkaXJlY3QgYWNjZXNzIHRvIGF0dHJpYnV0ZXNcbiAqL1xuZnVuY3Rpb24gY3JlYXRlVG9tZVByb3h5KHRvbWU6IGFueSwgY3RvcjogYW55KTogYW55IHtcbiAgY29uc3QgdHlwZU1hcDogYW55ID0ge31cbiAgY29uc3QgcHJveHk6IGFueSA9IG5ldyBQcm94eSh0b21lLCB7XG4gICAgICBvd25LZXlzKHRhcmdldCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXModGFyZ2V0KS5jb25jYXQoW1xuICAgICAgICAgICdfX2RpcnR5X18nLFxuICAgICAgICAgICdfX3Jvb3RfXycsXG4gICAgICAgICAgJ19fZGlmZl9fJyxcbiAgICAgICAgICAnX19kaWZmRW5hYmxlZF9fJyxcbiAgICAgICAgICAnX192ZXJzaW9uX18nLFxuICAgICAgICAgICdfX3BhcmVudF9fJyxcbiAgICAgICAgICAnX19rZXlfXydcbiAgICAgICAgXSlcbiAgICAgIH0sXG4gICAgICBnZXRQcm90b3R5cGVPZih0YXJnZXQpIHtcbiAgICAgICAgaWYgKEFycmF5VG9tZS5pc0FycmF5VG9tZSh0YXJnZXQpKSB7XG4gICAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZVxuICAgICAgICB9XG5cbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgICovXG4gICAgICAgIHJldHVybiBjdG9yLnByb3RvdHlwZSB8fCBPYmplY3QucHJvdG90eXBlXG4gICAgICB9LFxuICAgICAgZ2V0KHRhcmdldDogYW55LCBrZXk6IGFueSkge1xuICAgICAgICAvLyBSZXR1cm4gYSBzdHJpbmdpZmllZCBvYmplY3QvYXJyYXkvZXRjXG4gICAgICAgIGlmIChrZXkgPT09ICd0b1N0cmluZycgfHwga2V5ID09PSBTeW1ib2wudG9TdHJpbmdUYWcpIHtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlVG9TdHJpbmcodGFyZ2V0KVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gdGhlIHR5cGUgZGVmaW5pdGlvbiBmb3IgdXRpbC5pbnNwZWN0LmN1c3RvbSBzZWVtcyB0byBiZSBtaXNzaW5nXG4gICAgICAgIGlmIChrZXkgPT09ICdpbnNwZWN0JyB8fCBrZXkgPT09ICg8YW55PiBpbnNwZWN0KS5jdXN0b20pIHtcbiAgICAgICAgICBsZXQgbmFtZTogc3RyaW5nXG4gICAgICAgICAgaWYgKEFycmF5VG9tZS5pc0FycmF5VG9tZSh0YXJnZXQpKSB7XG4gICAgICAgICAgICBuYW1lID0gJ0FycmF5J1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuYW1lID0gY3Rvci5uYW1lXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIGNyZWF0ZUluc3BlY3QodGFyZ2V0LCBuYW1lKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmV0dXJuIHRoZSBkYXRhIHN0cnVjdHVyZSdzIHN0YW5kYXJkIGl0ZXJhdG9yXG4gICAgICAgIGlmIChrZXkgPT09IFN5bWJvbC5pdGVyYXRvcikge1xuICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgICAgICAgaWYgKEFycmF5VG9tZS5pc0FycmF5VG9tZSh0YXJnZXQpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGFyZ2V0XG4gICAgICAgICAgICAgIC52YWx1ZU9mKClcbiAgICAgICAgICAgICAgLm1hcCgodDogYW55KSA9PiBwcm94aWZ5T3JVbnRvbWUodCwgY3RvcikpW1N5bWJvbC5pdGVyYXRvcl1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCovXG4gICAgICAgICAgcmV0dXJuIHRhcmdldFtTeW1ib2wuaXRlcmF0b3JdXG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXR1cm4gdGhlIGNvcnJlY3QgY29uc3RydWN0b3IgLSB3ZSB3YW50XG4gICAgICAgIC8vIEFycmF5VG9tZXMgdG8gYXBwZWFyIGFzIGJlaW5nIEFycmF5cyxcbiAgICAgICAgLy8gYW5kIGV2ZXJ5dGhpbmcgZWxzZSBhcyB0aGUga25vd24gdHlwZVxuICAgICAgICBpZiAoa2V5ID09PSAnY29uc3RydWN0b3InKSB7XG4gICAgICAgICAgaWYgKEFycmF5VG9tZS5pc0FycmF5VG9tZSh0YXJnZXQpKSB7XG4gICAgICAgICAgICByZXR1cm4gQXJyYXlcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gY3RvclxuICAgICAgICB9XG5cbiAgICAgICAgLy8gRXh0cmFjdCB0aGUgdmFsdWVcbiAgICAgICAgY29uc3QgdmFsID0gdGFyZ2V0W2tleV1cblxuICAgICAgICAvLyBVbmRlZmluZWQgbWVhbnMgZWl0aGVyIHRoZSB2YWx1ZSBpcyB1bmRlZmluZWQsXG4gICAgICAgIC8vIG9yIHdlIGFyZSB0cnlpbmcgdG8gYWNjZXNzIGEgcHJvdG90eXBlIG1ldGhvZFxuICAgICAgICBpZiAodmFsID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBpZiAoY3Rvci5wcm90b3R5cGVba2V5XSkge1xuICAgICAgICAgICAgcmV0dXJuIGN0b3IucHJvdG90eXBlW2tleV0uYmluZChwcm94eSlcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gdmFsXG4gICAgICAgIH1cblxuICAgICAgICAvLyBDcmVhdGUgYSBPYmplY3RUb21lIG9yIEFycmF5VG9tZSBwcm94eVxuICAgICAgICBpZiAoT2JqZWN0VG9tZS5pc09iamVjdFRvbWUodmFsKSB8fCBBcnJheVRvbWUuaXNBcnJheVRvbWUodmFsKSkge1xuICAgICAgICAgIGlmIChBcnJheVRvbWUuaXNBcnJheVRvbWUodGFyZ2V0KSkge1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZVRvbWVQcm94eSh2YWwsIGN0b3IpXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgdHlwZUluZm8gPSBkZWZhdWx0TWV0YWRhdGFTdG9yYWdlLmZpbmRUeXBlTWV0YWRhdGEoY3RvciwgPHN0cmluZz4ga2V5KVxuICAgICAgICAgIGNvbnN0IGNoaWxkQ3RvciA9IGV4dHJhY3RUeXBlKHR5cGVJbmZvLCB0eXBlTWFwLCBrZXkpXG5cbiAgICAgICAgICByZXR1cm4gY3JlYXRlVG9tZVByb3h5KHRhcmdldFtrZXldLCBjaGlsZEN0b3IpXG4gICAgICAgIH1cblxuICAgICAgICAvLyBNYW5nbGUgYXJyYXkgZnVuY3Rpb25zIHNvIHRoYXQgdGhleSBrZWVwIHRoZSBwcm9wZXJcbiAgICAgICAgLy8gY29udGV4dCBhbmQgcHJveHkgc2libGluZ3Mgd2hlbiBuZWVkZWRcbiAgICAgICAgaWYgKHR5cGVvZiB2YWwgPT09ICdmdW5jdGlvbicgJiYgQXJyYXlUb21lLmlzQXJyYXlUb21lKHRhcmdldCkpIHtcbiAgICAgICAgICByZXR1cm4gcHJvY2Vzc0FycmF5VG9tZU1ldGhvZFJlcXVlc3QodGFyZ2V0LCBrZXksIGN0b3IpXG4gICAgICAgIH1cblxuICAgICAgICAvLyBUT0RPOiBtYXAgb2JqZWN0IG1ldGhvZCBjYWxscyB0byB0aGVpciBcInJlYWxcIiBwcm90b3R5cGVcblxuICAgICAgICAvLyBJbiBhbGwgb3RoZXIgY2FzZXMsIHJldHVybiB0aGUgdW5kZXJseWluZyB2YWx1ZSBvZiB0aGUgYXR0cmlidXRlXG4gICAgICAgIHJldHVybiB2YWwudmFsdWVPZigpXG4gICAgICB9LFxuICAgICAgc2V0KHRhcmdldDogYW55LCBrZXk6IHN0cmluZywgdmFsdWUpIHtcbiAgICAgICAgdGFyZ2V0LnNldChrZXksIHZhbHVlKVxuXG4gICAgICAgIHR5cGVNYXBba2V5XSA9IHVuZGVmaW5lZFxuXG4gICAgICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsKSB7XG4gICAgICAgICAgdHlwZU1hcFtrZXldID0gdmFsdWUuY29uc3RydWN0b3JcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICB9LFxuICAgICAgZGVsZXRlUHJvcGVydHkoX3RhcmdldCwga2V5OiBzdHJpbmcpIHtcbiAgICAgICAgdG9tZS5kZWwoa2V5KVxuXG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICB9XG4gICAgfSlcblxuICByZXR1cm4gcHJveHlcbn1cblxuLyoqXG4gKiBEZWFsaW5nIHdpdGggdG9tZSB0b3BpY3NcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVmFsaWRhdGVkVG9tZVRvcGljIGV4dGVuZHMgVmFsaWRhdGVkVG9waWMge1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IG1lZGlhVHlwZSA9ICdhcHBsaWNhdGlvbi94LXRvbWUnXG5cbiAgcHVibGljIHN0YXRpYyBhc3luYyBjcmVhdGU8SSBleHRlbmRzIGFyY2hpdmlzdC5JQXJjaGl2aXN0SW5kZXgsIFQgZXh0ZW5kcyBWYWxpZGF0ZWRUb3BpYz4oXG4gICAgdGhpczogSVN0YXRpY1RoaXM8SSwgVD4sXG4gICAgc3RhdGU6IG1hZ2UuY29yZS5JU3RhdGUsXG4gICAgaW5kZXg6IEksXG4gICAgZGF0YT86IFRvcGljRGF0YTxUPlxuICApOiBQcm9taXNlPFQ+IHtcblxuICAgIGNvbnN0IGNsYXNzTmFtZSA9IHRoaXMuZ2V0Q2xhc3NOYW1lKClcbiAgICBjb25zdCB0eXBlTWFwOiBhbnkgPSB7fVxuXG4gICAgY29uc3QgaXNUb21lID0gVG9tZS5pc1RvbWUoZGF0YSlcbiAgICBjb25zdCByYXdEYXRhOiBhbnkgPSBpc1RvbWUgPyBUb21lLnVuVG9tZShkYXRhKSA6IGRhdGFcbiAgICBjb25zdCBpbnN0YW5jZSA9IGNsYXNzVHJhbnNmb3JtZXIucGxhaW5Ub0NsYXNzPFQsIG9iamVjdD4odGhpcywgcmF3RGF0YSkgfHwgbmV3IHRoaXMoKVxuICAgIGNvbnN0IHRvbWU6IGFueSA9IGlzVG9tZSA/IGRhdGEgOiBUb21lLmNvbmp1cmUoaW5zdGFuY2UpXG5cbiAgICBpbnN0YW5jZS5zZXRUb3BpYyhjbGFzc05hbWUpXG4gICAgaW5zdGFuY2Uuc2V0U3RhdGUoc3RhdGUpXG5cbiAgICBhd2FpdCBpbnN0YW5jZS5zZXRJbmRleChpbmRleClcblxuICAgIGNvbnN0IHByb3h5OiBhbnkgPSBuZXcgUHJveHkoaW5zdGFuY2UsIHtcbiAgICAgIG93bktleXMoKSB7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0b21lKVxuICAgICAgfSxcbiAgICAgIGdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQ6IGFueSwga2V5KSB7XG4gICAgICAgcmV0dXJuIHsgY29uZmlndXJhYmxlOiB0cnVlLCBlbnVtZXJhYmxlOiB0cnVlLCB2YWx1ZTogdGhpcy5nZXQodGFyZ2V0LCBrZXkpIH1cbiAgICAgIH0sXG4gICAgICBnZXQodGFyZ2V0OiBhbnksIGtleSkge1xuICAgICAgICBpZiAoa2V5ID09PSAndG9TdHJpbmcnIHx8IGtleSA9PT0gU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG4gICAgICAgICAgcmV0dXJuIGNyZWF0ZVRvU3RyaW5nKHRvbWUpXG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGUgdHlwZSBkZWZpbml0aW9uIGZvciB1dGlsLmluc3BlY3QuY3VzdG9tIHNlZW1zIHRvIGJlIG1pc3NpbmdcbiAgICAgICAgaWYgKGtleSA9PT0gJ2luc3BlY3QnIHx8IGtleSA9PT0gKDxhbnk+IGluc3BlY3QpLmN1c3RvbSkge1xuICAgICAgICAgIHJldHVybiBjcmVhdGVJbnNwZWN0KHRvbWUsIGNsYXNzTmFtZSlcbiAgICAgICAgfVxuXG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIGlmIChrZXkgPT09ICdzZXQnIHx8IGtleSA9PT0gJ2RlbCcpIHtcbiAgICAgICAgICByZXR1cm4gdGFyZ2V0W2tleV1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChrZXkgPT09ICdjb25zdHJ1Y3RvcicpIHtcbiAgICAgICAgICByZXR1cm4gdGFyZ2V0LmNvbnN0cnVjdG9yXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoa2V5ID09PSAnZ2V0RGF0YScpIHtcbiAgICAgICAgICByZXR1cm4gKCkgPT4gdG9tZVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0b21lW2tleV0pIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldFtrZXldID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4gdGFyZ2V0W2tleV0uYmluZChwcm94eSlcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoa2V5ID09PSAnX3N0YXRlJyB8fCBrZXkgPT09ICdfdG9waWMnIHx8IGtleSA9PT0gJ19pbmRleCcgKSB7XG4gICAgICAgICAgICByZXR1cm4gdGFyZ2V0W2tleV1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoT2JqZWN0VG9tZS5pc09iamVjdFRvbWUodG9tZVtrZXldKSB8fCBBcnJheVRvbWUuaXNBcnJheVRvbWUodG9tZVtrZXldKSkge1xuICAgICAgICAgIGNvbnN0IHR5cGVJbmZvID0gZGVmYXVsdE1ldGFkYXRhU3RvcmFnZS5maW5kVHlwZU1ldGFkYXRhKHRhcmdldC5jb25zdHJ1Y3RvciwgPHN0cmluZz4ga2V5KVxuICAgICAgICAgIGNvbnN0IGN0b3IgPSBleHRyYWN0VHlwZSh0eXBlSW5mbywgdHlwZU1hcCwga2V5KVxuXG4gICAgICAgICAgcmV0dXJuIGNyZWF0ZVRvbWVQcm94eSh0b21lW2tleV0sIGN0b3IpXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdG9tZVtrZXldLnZhbHVlT2YoKVxuICAgICAgfSxcbiAgICAgIHNldChfdGFyZ2V0OiBhbnksIGtleSwgdmFsdWUpIHtcbiAgICAgICAgdG9tZS5zZXQoa2V5LCB2YWx1ZSlcblxuICAgICAgICB0eXBlTWFwW2tleV0gPSB1bmRlZmluZWRcblxuICAgICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCkge1xuICAgICAgICAgIHR5cGVNYXBba2V5XSA9IHZhbHVlLmNvbnN0cnVjdG9yXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgfSxcbiAgICAgIGRlbGV0ZVByb3BlcnR5KHRhcmdldCwga2V5KSB7XG4gICAgICAgIGNvbnN0IHZhbCA9IHRvbWVba2V5XVxuXG4gICAgICAgIGlmIChUb21lLmlzVG9tZSh2YWwpKSB7XG4gICAgICAgICAgdG9tZS5kZWwoa2V5KVxuICAgICAgICB9XG5cbiAgICAgICAgZGVsZXRlIHRhcmdldFtrZXldXG5cbiAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgIH1cbiAgICB9KVxuXG4gICAgcmV0dXJuIHByb3h5XG4gIH1cbn1cbiJdfQ==