mage-validator
Version:
Validation utility for MAGE user commands & topics (TypeScript)
280 lines • 33.9 kB
JavaScript
"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==