var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; export default class Validator { constructor() { this.steps = []; this.validationAttributes = []; } /** * @param thingName The name of the thing to validate. * @param value The value to verify. * @param onlyFormat {@code true} to only validate format properties, {@code false} otherwise. * @param connection A connection to use in case of wrapped transactions. */ execute(thingName, value, onlyFormat, connection) { return __awaiter(this, void 0, void 0, function* () { const bag = new ValidationBag(); for (const step of this.steps) { if (onlyFormat && !step.isFormat) continue; const result = step.verifyStep(value, thingName, connection); if ((result === false || result instanceof Promise && (yield result) === false) && step.throw) { const error = step.throw(); error.thingName = thingName; error.value = value; bag.addMessage(error); } else if (step.interrupt !== undefined && step.interrupt(value)) { break; } } if (bag.hasMessages()) { throw bag; } }); } defined() { this.validationAttributes.push('required'); this.addStep({ verifyStep: val => val !== undefined, throw: () => new UndefinedValueValidationError(), isFormat: true, }); return this; } acceptUndefined() { this.addStep({ verifyStep: () => true, throw: null, interrupt: val => val === undefined || val === null, isFormat: true, }); return this; } equals(other) { this.addStep({ verifyStep: val => val === other, throw: () => new BadValueValidationError(other), isFormat: true, }); return this; } regexp(regexp) { this.validationAttributes.push(`pattern="${regexp}"`); this.addStep({ verifyStep: val => regexp.test(val), throw: () => new InvalidFormatValidationError(), isFormat: true, }); return this; } length(length) { this.addStep({ verifyStep: val => val.length === length, throw: () => new BadLengthValidationError(length), isFormat: true, }); return this; } /** * @param minLength included * @param maxLength included */ between(minLength, maxLength) { this.addStep({ verifyStep: val => { const length = val.length; return length >= minLength && length <= maxLength; }, throw: () => new BadLengthValidationError(minLength, maxLength), isFormat: true, }); return this; } /** * @param min included */ min(min) { this.validationAttributes.push(`min="${min}"`); this._min = min; this.addStep({ verifyStep: val => { return val >= min; }, throw: () => new OutOfRangeValidationError(this._min, this._max), isFormat: true, }); return this; } /** * @param max included */ max(max) { this.validationAttributes.push(`max="${max}"`); this._max = max; this.addStep({ verifyStep: val => { return val <= max; }, throw: () => new OutOfRangeValidationError(this._min, this._max), isFormat: true, }); return this; } unique(model, querySupplier) { this.addStep({ verifyStep: (val, thingName, c) => __awaiter(this, void 0, void 0, function* () { let query; if (querySupplier) { query = querySupplier().where(thingName, val); } else { query = model.constructor.select('1').where(thingName, val); } if (typeof model.id === 'number') query = query.whereNot('id', model.id); return (yield query.execute(c)).results.length === 0; }), throw: () => new AlreadyExistsValidationError(model.table), isFormat: false, }); return this; } exists(modelClass, foreignKey) { this.addStep({ verifyStep: (val, thingName, c) => __awaiter(this, void 0, void 0, function* () { return (yield modelClass.select('1').where(foreignKey !== undefined ? foreignKey : thingName, val).execute(c)).results.length >= 1; }), throw: () => new UnknownRelationValidationError(modelClass.table, foreignKey), isFormat: false, }); return this; } addStep(step) { this.steps.push(step); } getValidationAttributes() { return this.validationAttributes; } step(step) { this.validationAttributes.push(`step="${step}"`); return this; } } export class ValidationBag extends Error { constructor() { super(...arguments); this.messages = {}; } addMessage(err) { if (!err.thingName) { throw new Error('Null thing name'); } this.messages[err.thingName] = { name: err.name, message: err.message, value: err.value, }; } hasMessages() { return Object.keys(this.messages).length > 0; } getMessages() { return this.messages; } } export class ValidationError extends Error { get name() { return this.constructor.name; } } export class BadLengthValidationError extends ValidationError { constructor(expectedLength, maxLength) { super(); this.expectedLength = expectedLength; this.maxLength = maxLength; } get message() { return `${this.thingName} expected length: ${this.expectedLength}${this.maxLength !== undefined ? ` to ${this.maxLength}` : ''}; ` + `actual length: ${this.value.length}.`; } } export class BadValueValidationError extends ValidationError { constructor(expectedValue) { super(); this.expectedValue = expectedValue; } get message() { return `Expected: ${this.expectedValue}; got: ${this.value}.`; } } export class OutOfRangeValidationError extends ValidationError { constructor(min, max) { super(); this.min = min; this.max = max; } get message() { if (this.min === undefined) { return `${this.thingName} must be at most ${this.max}`; } else if (this.max === undefined) { return `${this.thingName} must be at least ${this.min}`; } return `${this.thingName} must be between ${this.min} and ${this.max}.`; } } export class InvalidFormatValidationError extends ValidationError { get message() { return `"${this.value}" is not a valid ${this.thingName}.`; } } export class UndefinedValueValidationError extends ValidationError { get message() { return `${this.thingName} is required.`; } } export class AlreadyExistsValidationError extends ValidationError { constructor(table) { super(); this.table = table; } get message() { return `${this.value} already exists in ${this.table}.${this.thingName}.`; } } export class UnknownRelationValidationError extends ValidationError { constructor(table, foreignKey) { super(); this.table = table; this.foreignKey = foreignKey; } get message() { return `${this.thingName}=${this.value} relation was not found in ${this.table}${this.foreignKey !== undefined ? `.${this.foreignKey}` : ''}.`; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVmFsaWRhdG9yLmpzIiwic291cmNlUm9vdCI6Ii4vIiwic291cmNlcyI6WyJkYi9WYWxpZGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBSUEsTUFBTSxDQUFDLE9BQU8sT0FBTyxTQUFTO0lBQTlCO1FBQ3FCLFVBQUssR0FBd0IsRUFBRSxDQUFDO1FBQ2hDLHlCQUFvQixHQUFhLEVBQUUsQ0FBQztJQXlLekQsQ0FBQztJQXBLRzs7Ozs7T0FLRztJQUNHLE9BQU8sQ0FBQyxTQUFpQixFQUFFLEtBQW9CLEVBQUUsVUFBbUIsRUFBRSxVQUF1Qjs7WUFDL0YsTUFBTSxHQUFHLEdBQUcsSUFBSSxhQUFhLEVBQUUsQ0FBQztZQUVoQyxLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUU7Z0JBQzNCLElBQUksVUFBVSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVE7b0JBQUUsU0FBUztnQkFFM0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLFVBQVUsQ0FBQyxDQUFDO2dCQUM3RCxJQUFJLENBQUMsTUFBTSxLQUFLLEtBQUssSUFBSSxNQUFNLFlBQVksT0FBTyxJQUFJLENBQUMsTUFBTSxNQUFNLENBQUMsS0FBSyxLQUFLLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFO29CQUMzRixNQUFNLEtBQUssR0FBb0IsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUM1QyxLQUFLLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztvQkFDNUIsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7b0JBQ3BCLEdBQUcsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7aUJBQ3pCO3FCQUFNLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRTtvQkFDOUQsTUFBTTtpQkFDVDthQUNKO1lBRUQsSUFB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LEVBQUUsR0FBRyxDQUFDO0lBQ25KLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBNb2RlbCBmcm9tIFwiLi9Nb2RlbFwiO1xuaW1wb3J0IFF1ZXJ5IGZyb20gXCIuL1F1ZXJ5XCI7XG5pbXBvcnQge0Nvbm5lY3Rpb259IGZyb20gXCJteXNxbFwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBWYWxpZGF0b3I8VD4ge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgc3RlcHM6IFZhbGlkYXRpb25TdGVwPFQ+W10gPSBbXTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IHZhbGlkYXRpb25BdHRyaWJ1dGVzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgcHJpdmF0ZSBfbWluPzogbnVtYmVyO1xuICAgIHByaXZhdGUgX21heD86IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB0aGluZ05hbWUgVGhlIG5hbWUgb2YgdGhlIHRoaW5nIHRvIHZhbGlkYXRlLlxuICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgdmFsdWUgdG8gdmVyaWZ5LlxuICAgICAqIEBwYXJhbSBvbmx5Rm9ybWF0IHtAY29kZSB0cnVlfSB0byBvbmx5IHZhbGlkYXRlIGZvcm1hdCBwcm9wZXJ0aWVzLCB7QGNvZGUgZmFsc2V9IG90aGVyd2lzZS5cbiAgICAgKiBAcGFyYW0gY29ubmVjdGlvbiBBIGNvbm5lY3Rpb24gdG8gdXNlIGluIGNhc2Ugb2Ygd3JhcHBlZCB0cmFuc2FjdGlvbnMuXG4gICAgICovXG4gICAgYXN5bmMgZXhlY3V0ZSh0aGluZ05hbWU6IHN0cmluZywgdmFsdWU6IFQgfCB1bmRlZmluZWQsIG9ubHlGb3JtYXQ6IGJvb2xlYW4sIGNvbm5lY3Rpb24/OiBDb25uZWN0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGJhZyA9IG5ldyBWYWxpZGF0aW9uQmFnKCk7XG5cbiAgICAgICAgZm9yIChjb25zdCBzdGVwIG9mIHRoaXMuc3RlcHMpIHtcbiAgICAgICAgICAgIGlmIChvbmx5Rm9ybWF0ICYmICFzdGVwLmlzRm9ybWF0KSBjb250aW51ZTtcblxuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gc3RlcC52ZXJpZnlTdGVwKHZhbHVlLCB0aGluZ05hbWUsIGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgaWYgKChyZXN1bHQgPT09IGZhbHNlIHx8IHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UgJiYgKGF3YWl0IHJlc3VsdCkgPT09IGZhbHNlKSAmJiBzdGVwLnRocm93KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3I6IFZhbGlkYXRpb25FcnJvciA9IHN0ZXAudGhyb3coKTtcbiAgICAgICAgICAgICAgICBlcnJvci50aGluZ05hbWUgPSB0aGluZ05hbWU7XG4gICAgICAgICAgICAgICAgZXJyb3IudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICBiYWcuYWRkTWVzc2FnZShlcnJvcik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHN0ZXAuaW50ZXJydXB0ICE9PSB1bmRlZmluZWQgJiYgc3RlcC5pbnRlcnJ1cHQodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYmFnLmhhc01lc3NhZ2VzKCkpIHtcbiAgICAgICAgICAgIHRocm93IGJhZztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBkZWZpbmVkKCk6IFZhbGlkYXRvcjxUPiB7XG4gICAgICAgIHRoaXMudmFsaWRhdGlvbkF0dHJpYnV0ZXMucHVzaCgncmVxdWlyZWQnKTtcblxuICAgICAgICB0aGlzLmFkZFN0ZXAoe1xuICAgICAgICAgICAgdmVyaWZ5U3RlcDogdmFsID0+IHZhbCAhPT0gdW5kZWZpbmVkLFxuICAgICAgICAgICAgdGhyb3c6ICgpID0+IG5ldyBVbmRlZmluZWRWYWx1ZVZhbGlkYXRpb25FcnJvcigpLFxuICAgICAgICAgICAgaXNGb3JtYXQ6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBwdWJsaWMgYWNjZXB0VW5kZWZpbmVkKCk6IFZhbGlkYXRvcjxUPiB7XG4gICAgICAgIHRoaXMuYWRkU3RlcCh7XG4gICAgICAgICAgICB2ZXJpZnlTdGVwOiAoKSA9PiB0cnVlLFxuICAgICAgICAgICAgdGhyb3c6IG51bGwsXG4gICAgICAgICAgICBpbnRlcnJ1cHQ6IHZhbCA9PiB2YWwgPT09IHVuZGVmaW5lZCB8fCB2YWwgPT09IG51bGwsXG4gICAgICAgICAgICBpc0Zvcm1hdDogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHB1YmxpYyBlcXVhbHMob3RoZXI/OiBUKTogVmFsaWRhdG9yPFQ+IHtcbiAgICAgICAgdGhpcy5hZGRTdGVwKHtcbiAgICAgICAgICAgIHZlcmlmeVN0ZXA6IHZhbCA9PiB2YWwgPT09IG90aGVyLFxuICAgICAgICAgICAgdGhyb3c6ICgpID0+IG5ldyBCYWRWYWx1ZVZhbGlkYXRpb25FcnJvcihvdGhlciksXG4gICAgICAgICAgICBpc0Zvcm1hdDogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWdleHAocmVnZXhwOiBSZWdFeHApOiBWYWxpZGF0b3I8VD4ge1xuICAgICAgICB0aGlzLnZhbGlkYXRpb25BdHRyaWJ1dGVzLnB1c2goYHBhdHRlcm49XCIke3JlZ2V4cH1cImApO1xuICAgICAgICB0aGlzLmFkZFN0ZXAoe1xuICAgICAgICAgICAgdmVyaWZ5U3RlcDogdmFsID0+IHJlZ2V4cC50ZXN0KDxzdHJpbmc+PHVua25vd24+dmFsKSxcbiAgICAgICAgICAgIHRocm93OiAoKSA9PiBuZXcgSW52YWxpZEZvcm1hdFZhbGlkYXRpb25FcnJvcigpLFxuICAgICAgICAgICAgaXNGb3JtYXQ6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBwdWJsaWMgbGVuZ3RoKGxlbmd0aDogbnVtYmVyKTogVmFsaWRhdG9yPFQ+IHtcbiAgICAgICAgdGhpcy5hZGRTdGVwKHtcbiAgICAgICAgICAgIHZlcmlmeVN0ZXA6IHZhbCA9PiAoPGFueT52YWwpLmxlbmd0aCA9PT0gbGVuZ3RoLFxuICAgICAgICAgICAgdGhyb3c6ICgpID0+IG5ldyBCYWRMZW5ndGhWYWxpZGF0aW9uRXJyb3IobGVuZ3RoKSxcbiAgICAgICAgICAgIGlzRm9ybWF0OiB0cnVlLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG1pbkxlbmd0aCBpbmNsdWRlZFxuICAgICAqIEBwYXJhbSBtYXhMZW5ndGggaW5jbHVkZWRcbiAgICAgKi9cbiAgICBwdWJsaWMgYmV0d2VlbihtaW5MZW5ndGg6IG51bWJlciwgbWF4TGVuZ3RoOiBudW1iZXIpOiBWYWxpZGF0b3I8VD4ge1xuICAgICAgICB0aGlzLmFkZFN0ZXAoe1xuICAgICAgICAgICAgdmVyaWZ5U3RlcDogdmFsID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBsZW5ndGggPSAoPGFueT52YWwpLmxlbmd0aDtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVuZ3RoID49IG1pbkxlbmd0aCAmJiBsZW5ndGggPD0gbWF4TGVuZ3RoO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRocm93OiAoKSA9PiBuZXcgQmFkTGVuZ3RoVmFsaWRhdGlvbkVycm9yKG1pbkxlbmd0aCwgbWF4TGVuZ3RoKSxcbiAgICAgICAgICAgIGlzRm9ybWF0OiB0cnVlLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG1pbiBpbmNsdWRlZFxuICAgICAqL1xuICAgIHB1YmxpYyBtaW4obWluOiBudW1iZXIpOiBWYWxpZGF0b3I8VD4ge1xuICAgICAgICB0aGlzLnZhbGlkYXRpb25BdHRyaWJ1dGVzLnB1c2goYG1pbj1cIiR7bWlufVwiYCk7XG4gICAgICAgIHRoaXMuX21pbiA9IG1pbjtcbiAgICAgICAgdGhpcy5hZGRTdGVwKHtcbiAgICAgICAgICAgIHZlcmlmeVN0ZXA6IHZhbCA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICg8YW55PnZhbCkgPj0gbWluO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRocm93OiAoKSA9PiBuZXcgT3V0T2ZSYW5nZVZhbGlkYXRpb25FcnJvcih0aGlzLl9taW4sIHRoaXMuX21heCksXG4gICAgICAgICAgICBpc0Zvcm1hdDogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBtYXggaW5jbHVkZWRcbiAgICAgKi9cbiAgICBwdWJsaWMgbWF4KG1heDogbnVtYmVyKTogVmFsaWRhdG9yPFQ+IHtcbiAgICAgICAgdGhpcy52YWxpZGF0aW9uQXR0cmlidXRlcy5wdXNoKGBtYXg9XCIke21heH1cImApO1xuICAgICAgICB0aGlzLl9tYXggPSBtYXg7XG4gICAgICAgIHRoaXMuYWRkU3RlcCh7XG4gICAgICAgICAgICB2ZXJpZnlTdGVwOiB2YWwgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiAoPGFueT52YWwpIDw9IG1heDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0aHJvdzogKCkgPT4gbmV3IE91dE9mUmFuZ2VWYWxpZGF0aW9uRXJyb3IodGhpcy5fbWluLCB0aGlzLl9tYXgpLFxuICAgICAgICAgICAgaXNGb3JtYXQ6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBwdWJsaWMgdW5pcXVlKG1vZGVsOiBNb2RlbCwgcXVlcnlTdXBwbGllcj86ICgpID0+IFF1ZXJ5KTogVmFsaWRhdG9yPFQ+IHtcbiAgICAgICAgdGhpcy5hZGRTdGVwKHtcbiAgICAgICAgICAgIHZlcmlmeVN0ZXA6IGFzeW5jICh2YWwsIHRoaW5nTmFtZSwgYykgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBxdWVyeTogUXVlcnk7XG4gICAgICAgICAgICAgICAgaWYgKHF1ZXJ5U3VwcGxpZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgcXVlcnkgPSBxdWVyeVN1cHBsaWVyKCkud2hlcmUodGhpbmdOYW1lLCB2YWwpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHF1ZXJ5ID0gKDxhbnk+bW9kZWwuY29uc3RydWN0b3IpLnNlbGVjdCgnMScpLndoZXJlKHRoaW5nTmFtZSwgdmFsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtb2RlbC5pZCA9PT0gJ251bWJlcicpIHF1ZXJ5ID0gcXVlcnkud2hlcmVOb3QoJ2lkJywgbW9kZWwuaWQpO1xuICAgICAgICAgICAgICAgIHJldHVybiAoYXdhaXQgcXVlcnkuZXhlY3V0ZShjKSkucmVzdWx0cy5sZW5ndGggPT09IDA7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGhyb3c6ICgpID0+IG5ldyBBbHJlYWR5RXhpc3RzVmFsaWRhdGlvbkVycm9yKG1vZGVsLnRhYmxlKSxcbiAgICAgICAgICAgIGlzRm9ybWF0OiBmYWxzZSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHB1YmxpYyBleGlzdHMobW9kZWxDbGFzczogRnVuY3Rpb24sIGZvcmVpZ25LZXk/OiBzdHJpbmcpOiBWYWxpZGF0b3I8VD4ge1xuICAgICAgICB0aGlzLmFkZFN0ZXAoe1xuICAgICAgICAgICAgdmVyaWZ5U3RlcDogYXN5bmMgKHZhbCwgdGhpbmdOYW1lLCBjKSA9PiAoYXdhaXQgKDxhbnk+bW9kZWxDbGFzcykuc2VsZWN0KCcxJykud2hlcmUoZm9yZWlnbktleSAhPT0gdW5kZWZpbmVkID8gZm9yZWlnbktleSA6IHRoaW5nTmFtZSwgdmFsKS5leGVjdXRlKGMpKS5yZXN1bHRzLmxlbmd0aCA+PSAxLFxuICAgICAgICAgICAgdGhyb3c6ICgpID0+IG5ldyBVbmtub3duUmVsYXRpb25WYWxpZGF0aW9uRXJyb3IoKDxhbnk+bW9kZWxDbGFzcykudGFibGUsIGZvcmVpZ25LZXkpLFxuICAgICAgICAgICAgaXNGb3JtYXQ6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhZGRTdGVwKHN0ZXA6IFZhbGlkYXRpb25TdGVwPFQ+KSB7XG4gICAgICAgIHRoaXMuc3RlcHMucHVzaChzdGVwKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0VmFsaWRhdGlvbkF0dHJpYnV0ZXMoKTogc3RyaW5nW10ge1xuICAgICAgICByZXR1cm4gdGhpcy52YWxpZGF0aW9uQXR0cmlidXRlcztcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RlcChzdGVwOiBudW1iZXIpOiBWYWxpZGF0b3I8VD4ge1xuICAgICAgICB0aGlzLnZhbGlkYXRpb25BdHRyaWJ1dGVzLnB1c2goYHN0ZXA9XCIke3N0ZXB9XCJgKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxufVxuXG5pbnRlcmZhY2UgVmFsaWRhdGlvblN0ZXA8VD4ge1xuICAgIGludGVycnVwdD86ICh2YWw/OiBUKSA9PiBib29sZWFuO1xuXG4gICAgdmVyaWZ5U3RlcCh2YWw6IFQgfCB1bmRlZmluZWQsIHRoaW5nTmFtZTogc3RyaW5nLCBjb25uZWN0aW9uPzogQ29ubmVjdGlvbik6IGJvb2xlYW4gfCBQcm9taXNlPGJvb2xlYW4+O1xuXG4gICAgdGhyb3c6ICgodmFsPzogVCkgPT4gVmFsaWRhdGlvbkVycm9yKSB8IG51bGw7XG5cbiAgICByZWFkb25seSBpc0Zvcm1hdDogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNsYXNzIFZhbGlkYXRpb25CYWcgZXh0ZW5kcyBFcnJvciB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBtZXNzYWdlczogeyBbcDogc3RyaW5nXTogYW55IH0gPSB7fTtcblxuICAgIHB1YmxpYyBhZGRNZXNzYWdlKGVycjogVmFsaWRhdGlvbkVycm9yKSB7XG4gICAgICAgIGlmICghZXJyLnRoaW5nTmFtZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOdWxsIHRoaW5nIG5hbWUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWVzc2FnZXNbZXJyLnRoaW5nTmFtZV0gPSB7XG4gICAgICAgICAgICBuYW1lOiBlcnIubmFtZSxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgdmFsdWU6IGVyci52YWx1ZSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaGFzTWVzc2FnZXMoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLm1lc3NhZ2VzKS5sZW5ndGggPiAwO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRNZXNzYWdlcygpOiB7IFtwOiBzdHJpbmddOiBWYWxpZGF0aW9uRXJyb3IgfSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICAgIH1cbn1cblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFZhbGlkYXRpb25FcnJvciBleHRlbmRzIEVycm9yIHtcbiAgICBwdWJsaWMgdGhpbmdOYW1lPzogc3RyaW5nO1xuICAgIHB1YmxpYyB2YWx1ZT86IGFueTtcblxuICAgIHB1YmxpYyBnZXQgbmFtZSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIEJhZExlbmd0aFZhbGlkYXRpb25FcnJvciBleHRlbmRzIFZhbGlkYXRpb25FcnJvciB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBleHBlY3RlZExlbmd0aDogbnVtYmVyO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgbWF4TGVuZ3RoPzogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IoZXhwZWN0ZWRMZW5ndGg6IG51bWJlciwgbWF4TGVuZ3RoPzogbnVtYmVyKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuZXhwZWN0ZWRMZW5ndGggPSBleHBlY3RlZExlbmd0aDtcbiAgICAgICAgdGhpcy5tYXhMZW5ndGggPSBtYXhMZW5ndGg7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBtZXNzYWdlKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBgJHt0aGlzLnRoaW5nTmFtZX0gZXhwZWN0ZWQgbGVuZ3RoOiAke3RoaXMuZXhwZWN0ZWRMZW5ndGh9JHt0aGlzLm1heExlbmd0aCAhPT0gdW5kZWZpbmVkID8gYCB0byAke3RoaXMubWF4TGVuZ3RofWAgOiAnJ307IGAgK1xuICAgICAgICAgICAgYGFjdHVhbCBsZW5ndGg6ICR7dGhpcy52YWx1ZS5sZW5ndGh9LmA7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgQmFkVmFsdWVWYWxpZGF0aW9uRXJyb3IgZXh0ZW5kcyBWYWxpZGF0aW9uRXJyb3Ige1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZXhwZWN0ZWRWYWx1ZTogYW55O1xuXG4gICAgY29uc3RydWN0b3IoZXhwZWN0ZWRWYWx1ZTogYW55KSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuZXhwZWN0ZWRWYWx1ZSA9IGV4cGVjdGVkVmFsdWU7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBtZXNzYWdlKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBgRXhwZWN0ZWQ6ICR7dGhpcy5leHBlY3RlZFZhbHVlfTsgZ290OiAke3RoaXMudmFsdWV9LmBcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBPdXRPZlJhbmdlVmFsaWRhdGlvbkVycm9yIGV4dGVuZHMgVmFsaWRhdGlvbkVycm9yIHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IG1pbj86IG51bWJlcjtcbiAgICBwcml2YXRlIHJlYWRvbmx5IG1heD86IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKG1pbj86IG51bWJlciwgbWF4PzogbnVtYmVyKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMubWluID0gbWluO1xuICAgICAgICB0aGlzLm1heCA9IG1heDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IG1lc3NhZ2UoKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHRoaXMubWluID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBgJHt0aGlzLnRoaW5nTmFtZX0gbXVzdCBiZSBhdCBtb3N0ICR7dGhpcy5tYXh9YDtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLm1heCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gYCR7dGhpcy50aGluZ05hbWV9IG11c3QgYmUgYXQgbGVhc3QgJHt0aGlzLm1pbn1gO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBgJHt0aGlzLnRoaW5nTmFtZX0gbXVzdCBiZSBiZXR3ZWVuICR7dGhpcy5taW59IGFuZCAke3RoaXMubWF4fS5gO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIEludmFsaWRGb3JtYXRWYWxpZGF0aW9uRXJyb3IgZXh0ZW5kcyBWYWxpZGF0aW9uRXJyb3Ige1xuICAgIHB1YmxpYyBnZXQgbWVzc2FnZSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gYFwiJHt0aGlzLnZhbHVlfVwiIGlzIG5vdCBhIHZhbGlkICR7dGhpcy50aGluZ05hbWV9LmA7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgVW5kZWZpbmVkVmFsdWVWYWxpZGF0aW9uRXJyb3IgZXh0ZW5kcyBWYWxpZGF0aW9uRXJyb3Ige1xuICAgIHB1YmxpYyBnZXQgbWVzc2FnZSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy50aGluZ05hbWV9IGlzIHJlcXVpcmVkLmA7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgQWxyZWFkeUV4aXN0c1ZhbGlkYXRpb25FcnJvciBleHRlbmRzIFZhbGlkYXRpb25FcnJvciB7XG4gICAgcHJpdmF0ZSByZWFkb25seSB0YWJsZTogc3RyaW5nO1xuXG4gICAgY29uc3RydWN0b3IodGFibGU6IHN0cmluZykge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLnRhYmxlID0gdGFibGU7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBtZXNzYWdlKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBgJHt0aGlzLnZhbHVlfSBhbHJlYWR5IGV4aXN0cyBpbiAke3RoaXMudGFibGV9LiR7dGhpcy50aGluZ05hbWV9LmA7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgVW5rbm93blJlbGF0aW9uVmFsaWRhdGlvbkVycm9yIGV4dGVuZHMgVmFsaWRhdGlvbkVycm9yIHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRhYmxlOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSByZWFkb25seSBmb3JlaWduS2V5Pzogc3RyaW5nO1xuXG4gICAgY29uc3RydWN0b3IodGFibGU6IHN0cmluZywgZm9yZWlnbktleT86IHN0cmluZykge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLnRhYmxlID0gdGFibGU7XG4gICAgICAgIHRoaXMuZm9yZWlnbktleSA9IGZvcmVpZ25LZXk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBtZXNzYWdlKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBgJHt0aGlzLnRoaW5nTmFtZX09JHt0aGlzLnZhbHVlfSByZWxhdGlvbiB3YXMgbm90IGZvdW5kIGluICR7dGhpcy50YWJsZX0ke3RoaXMuZm9yZWlnbktleSAhPT0gdW5kZWZpbmVkID8gYC4ke3RoaXMuZm9yZWlnbktleX1gIDogJyd9LmA7XG4gICAgfVxufSJdfQ==