speckoloo
Version:
Domain entites inspired by Speck
580 lines (466 loc) • 47.1 kB
JavaScript
'use strict';
var _ava = require('ava');
var _factory = require('./factory');
var _factory2 = _interopRequireDefault(_factory);
var _common = require('./common');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
(0, _ava.test)('Given simple schema and validData, when factory is called, should create property acessors to all and only the keys described in schema', t => {
const schema = {
myProp1: {},
myProp2: {},
myProp3: {}
};
const data = {
myProp1: 'a',
myProp2: 'b',
myProp3: 'c'
};
const factory = (0, _factory2.default)(schema);
const result = factory(data);
t.deepEqual(Object.keys(result), Object.keys(data));
});
(0, _ava.test)('Given schema with contexts and valid data, when factory is called, should create property acessors to all and only the keys described in schema', t => {
const schema = {
myProp1: {},
myProp2: {},
myProp3: {},
$contexts: {
context1: {},
context2: {}
}
};
const data = {
myProp1: 'a',
myProp2: 'b',
myProp3: 'c'
};
const factory = (0, _factory2.default)(schema);
const result = factory(data);
t.deepEqual(Object.keys(result), Object.keys(data));
});
(0, _ava.test)('Given simple schema and missing data, when factory is called, should create property acessors to all and only the keys described in schema', t => {
const schema = {
myProp1: {},
myProp2: {},
myProp3: {}
};
const data = {
myProp1: 'a',
myProp2: 'b'
};
const factory = (0, _factory2.default)(schema);
const result = factory(data);
t.is(Object.keys(result).length, 3);
});
(0, _ava.test)('Given valid data, when factory is called, then it should create an object with all keys from schema', t => {
const schema = {
myProp1: {},
myProp2: {},
myProp3: {}
};
const data = {
myProp1: 'a',
myProp2: 'b',
myProp3: 'c'
};
const factory = (0, _factory2.default)(schema);
const result = factory(data).toJSON();
t.deepEqual(result, data);
});
(0, _ava.test)('Given valid data, when factory is called, then it should create an object with `construtor` property pointing to the same factory', t => {
const schema = {
myProp1: {},
myProp2: {},
myProp3: {}
};
const data = {
myProp1: 'a',
myProp2: 'b',
myProp3: 'c'
};
const factory = (0, _factory2.default)(schema);
const result = factory(data);
t.is(result.constructor, factory);
});
(0, _ava.test)('Given two identical schemas, when an entity from the first one is created from an entity from the second one, then the factory must apply duck typing and return an object from the first type', t => {
const schema1 = {
myProp1: {},
myProp2: {},
myProp3: {}
};
const schema2 = {
myProp1: {},
myProp2: {},
myProp3: {}
};
const data = {
myProp1: 'a',
myProp2: 'b',
myProp3: 'c'
};
const instanceFactory = (0, _factory2.default)(schema1);
const anotherInstanceFactory = (0, _factory2.default)(schema2);
const result = instanceFactory(anotherInstanceFactory(data));
t.is(result.constructor, instanceFactory);
});
(0, _ava.test)('Given schema, when factory is called, then it should return an object which is not `instnaceof` the factory', t => {
const schema = {
myProp1: {},
myProp2: {},
myProp3: {}
};
const data = {
myProp1: 'a',
myProp2: 'b',
myProp3: 'c'
};
const factory = (0, _factory2.default)(schema);
const instance = factory(data);
const error = t.throws(() => instance instanceof factory);
t.regex(error.message, /function has non-object prototype/i);
});
(0, _ava.test)('Given already instantiated entity, when factory is called, then it should create a copy of the original data', t => {
const schema = {
myProp1: {},
myProp2: {},
myProp3: {}
};
const data = {
myProp1: 'a',
myProp2: 'b',
myProp3: 'c'
};
const factory = (0, _factory2.default)(schema);
const firstInstance = factory(data);
const secondInstance = factory(firstInstance);
t.not(secondInstance, firstInstance);
t.deepEqual(secondInstance, firstInstance);
});
(0, _ava.test)('Given data with extra fields, when factory is called, then it should create an object with only the keys from schema, dropping the unspecified ones', t => {
const schema = {
myProp1: {},
myProp2: {}
};
const data = {
myProp1: 'a',
myProp2: 'b',
unespecifiedField1: 'c'
};
const expected = {
myProp1: 'a',
myProp2: 'b'
};
const factory = (0, _factory2.default)(schema);
const result = factory(data).toJSON();
t.deepEqual(result, expected);
});
(0, _ava.test)('Given valid data, when factory is called, then it should create an object with all keys from schema', t => {
const schema = {
myProp1: {},
myProp2: {},
myProp3: {}
};
const data = {
myProp1: 'a',
myProp2: 'b',
myProp3: 'c'
};
const factory = (0, _factory2.default)(schema);
const result = factory(data).toJSON();
t.deepEqual(result, data);
});
(0, _ava.test)('Given data with extra fields, when factory is called, then it should create an object with only the keys from schema, dropping the unspecified ones', t => {
const schema = {
myProp1: {},
myProp2: {}
};
const data = {
myProp1: 'a',
myProp2: 'b',
unespecifiedField1: 'c'
};
const expected = {
myProp1: 'a',
myProp2: 'b'
};
const factory = (0, _factory2.default)(schema);
const result = factory(data).toJSON();
t.deepEqual(result, expected);
});
(0, _ava.test)('Given valid data with nested entity, when factory is called for parent entity, then it should create an object referencing the child entity', t => {
const childSchema = {
childProp1: {},
childProp2: {},
childProp3: {}
};
const childFactory = (0, _factory2.default)(childSchema);
const parentSchema = {
parentProp1: {},
childEntity: {
factory: childFactory
}
};
const parentFactory = (0, _factory2.default)(parentSchema);
const validData = {
parentProp1: 'a',
childEntity: {
childProp1: 'b',
childProp2: 'c',
childProp3: 'd'
}
};
const result = parentFactory(validData);
t.deepEqual(result.childEntity, childFactory(validData.childEntity));
});
(0, _ava.test)('Given nested child data with extra properties, when factory is called for parent entity, then it should create an object referencing the child entity excluding the extra properties', t => {
const childSchema = {
childProp1: {}
};
const childFactory = (0, _factory2.default)(childSchema);
const parentSchema = {
childEntity: {
factory: childFactory
}
};
const parentFactory = (0, _factory2.default)(parentSchema);
const extraPropertiesOnNestedChildData = {
childEntity: {
childProp1: 'b',
childProp2: 'c'
}
};
const expected = {
childEntity: {
childProp1: 'b'
}
};
const result = parentFactory(extraPropertiesOnNestedChildData).toJSON();
t.deepEqual(result, expected);
});
(0, _ava.test)('Given missing nested child data, when factory is called for parent entity, then it should create an object that does not contain the property related to the child entity', t => {
const childSchema = {
childProp1: {}
};
const childFactory = (0, _factory2.default)(childSchema);
const parentSchema = {
prop1: {},
childEntity: {
factory: childFactory
}
};
const parentFactory = (0, _factory2.default)(parentSchema);
const missingChildEntityData = {
prop1: 'a'
};
const expected = {
prop1: 'a'
};
const result = parentFactory(missingChildEntityData).toJSON();
t.deepEqual(result, expected);
});
(0, _ava.test)('Given valid data with nested entity, when factory is called for parent entity with data that is already an instance of child, then it should create an object referencing the child entity', t => {
const childSchema = {
childProp1: {},
childProp2: {},
childProp3: {}
};
const childFactory = (0, _factory2.default)(childSchema);
const parentSchema = {
parentProp1: {},
childEntity: {
factory: childFactory
}
};
const parentFactory = (0, _factory2.default)(parentSchema);
const validData = {
parentProp1: 'a',
childEntity: childFactory({
childProp1: 'b',
childProp2: 'c',
childProp3: 'd'
})
};
const result = parentFactory(validData);
t.deepEqual(result.childEntity, childFactory(validData.childEntity));
});
(0, _ava.test)('Given already instantiated composite entity, when factory is called, then it should create a copy of the original nested entity', t => {
const childSchema = {
childProp1: {},
childProp2: {},
childProp3: {}
};
const childFactory = (0, _factory2.default)(childSchema);
const parentSchema = {
parentProp1: {},
childEntity: {
factory: childFactory
}
};
const parentFactory = (0, _factory2.default)(parentSchema);
const validData = {
parentProp1: 'a',
childEntity: {
childProp1: 'b',
childProp2: 'c',
childProp3: 'd'
}
};
const firstInstance = parentFactory(validData);
const secondInstance = parentFactory(firstInstance);
t.not(secondInstance.childEntity, firstInstance.childEntity);
t.deepEqual(secondInstance.childEntity, firstInstance.childEntity);
});
(0, _ava.test)('Given schema with $methods, when factory is called, then it should create an object with all methods from schema', t => {
const schema = {
myProp1: {},
myProp2: {},
myProp3: {},
$methods: {
myMethod() {
return `${this.myProp1}, ${this.myProp2}, ${this.myProp3}`;
}
}
};
const data = {
myProp1: 'a',
myProp2: 'b',
myProp3: 'c'
};
const factory = (0, _factory2.default)(schema);
const result = factory(data).myMethod();
t.deepEqual(result, 'a, b, c');
});
(0, _ava.test)('Given no data, when factory is called, then it should properly return an empty entity', t => {
const schema = {
myProp1: {},
myProp2: {},
myProp3: {}
};
const factory = (0, _factory2.default)(schema);
const result = factory();
t.deepEqual(result.toJSON(), {});
});
(0, _ava.test)('Given data that does not contain any valid property, when factory is called, then it should return an empty entity', t => {
const schema = {
myProp1: {},
myProp2: {},
myProp3: {}
};
const factory = (0, _factory2.default)(schema);
const result = factory({
unexistentProp: 'x'
});
t.deepEqual(result.toJSON(), {});
});
(0, _ava.test)('Given schema with property `factory` as Number, when factory is called, then it should return an entity that contains the referred property', t => {
const schema = {
myProp1: {
fatory: Number
},
myProp2: {}
};
const factory = (0, _factory2.default)(schema);
const data = {
myProp2: '200'
};
const result = factory(data);
t.deepEqual(result.toJSON(), data);
});
(0, _ava.test)('Given schema with property `factory`, when factory is called with missing data for such property, then it should return an entity that does not contain the referred property', t => {
const schema = {
myProp1: {
fatory: String
},
myProp2: {}
};
const factory = (0, _factory2.default)(schema);
const data = {
myProp2: 'a'
};
const result = factory(data);
t.deepEqual(result.toJSON(), data);
t.is(result.myProp1, undefined);
});
(0, _ava.test)('Given data that is not an object, when factory is called, then it should return an empty entity', t => {
const schema = {
myProp1: {},
myProp2: {},
myProp3: {},
toUpperCase: {}, // will it blow up for string?
length: {} // will it blow up for arrays?
};
const factory = (0, _factory2.default)(schema);
const invalidParams = [null, 'some string', [], ['non-empty array'], 123123, Symbol('foo'), /regex/];
invalidParams.map(param => {
t.deepEqual(factory(param).toJSON(), {});
});
});
(0, _ava.test)('Given data with no value for nested entity, when factory is called for parent entity, then the resulting object should not have a property for such nested entity', t => {
const childSchema = {
childProp1: {},
childProp2: {},
childProp3: {}
};
const childFactory = (0, _factory2.default)(childSchema);
const parentSchema = {
parentProp1: {},
childEntity: {
factory: childFactory
}
};
const parentFactory = (0, _factory2.default)(parentSchema);
const missingData = {
parentProp1: 'a'
};
const result = parentFactory(missingData);
t.deepEqual(result.toJSON(), missingData);
});
(0, _ava.test)('Given data with falsy value for nested entity, when factory is called for parent entity, then the resulting object should not have a property for such nested entity', t => {
const childSchema = {
childProp1: {},
childProp2: {},
childProp3: {}
};
const childFactory = (0, _factory2.default)(childSchema);
const parentSchema = {
parentProp1: {},
childEntity: {
factory: childFactory
}
};
const parentFactory = (0, _factory2.default)(parentSchema);
const falsyValues = [undefined, null, false, '', 0, NaN];
falsyValues.map(value => {
const invalidData = {
parentProp1: 'a',
childEntity: null
};
const result = parentFactory(invalidData);
t.deepEqual(result.toJSON(), (0, _common.pick)(invalidData, ['parentProp1']), `Failed for ${value}`);
});
});
(0, _ava.test)('Given data with truthy non-object value for nested entity, when factory is called for parent entity, then the resulting object should have a property with an empty value for such nested entity', t => {
const childSchema = {
childProp1: {},
childProp2: {},
childProp3: {}
};
const childFactory = (0, _factory2.default)(childSchema);
const parentSchema = {
parentProp1: {},
childEntity: {
factory: childFactory
}
};
const parentFactory = (0, _factory2.default)(parentSchema);
const truthyValues = [true, 'non-empty string', 1];
truthyValues.map(value => {
const invalidData = {
parentProp1: 'a',
childEntity: true
};
const result = parentFactory(invalidData);
t.deepEqual(result.toJSON().childEntity, {}, `Failed for ${value}`);
});
});
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9mYWN0b3J5LnRlc3QuanMiXSwibmFtZXMiOlsidCIsInNjaGVtYSIsIm15UHJvcDEiLCJteVByb3AyIiwibXlQcm9wMyIsImRhdGEiLCJmYWN0b3J5IiwicmVzdWx0IiwiZGVlcEVxdWFsIiwiT2JqZWN0Iiwia2V5cyIsIiRjb250ZXh0cyIsImNvbnRleHQxIiwiY29udGV4dDIiLCJpcyIsImxlbmd0aCIsInRvSlNPTiIsImNvbnN0cnVjdG9yIiwic2NoZW1hMSIsInNjaGVtYTIiLCJpbnN0YW5jZUZhY3RvcnkiLCJhbm90aGVySW5zdGFuY2VGYWN0b3J5IiwiaW5zdGFuY2UiLCJlcnJvciIsInRocm93cyIsInJlZ2V4IiwibWVzc2FnZSIsImZpcnN0SW5zdGFuY2UiLCJzZWNvbmRJbnN0YW5jZSIsIm5vdCIsInVuZXNwZWNpZmllZEZpZWxkMSIsImV4cGVjdGVkIiwiY2hpbGRTY2hlbWEiLCJjaGlsZFByb3AxIiwiY2hpbGRQcm9wMiIsImNoaWxkUHJvcDMiLCJjaGlsZEZhY3RvcnkiLCJwYXJlbnRTY2hlbWEiLCJwYXJlbnRQcm9wMSIsImNoaWxkRW50aXR5IiwicGFyZW50RmFjdG9yeSIsInZhbGlkRGF0YSIsImV4dHJhUHJvcGVydGllc09uTmVzdGVkQ2hpbGREYXRhIiwicHJvcDEiLCJtaXNzaW5nQ2hpbGRFbnRpdHlEYXRhIiwiJG1ldGhvZHMiLCJteU1ldGhvZCIsInVuZXhpc3RlbnRQcm9wIiwiZmF0b3J5IiwiTnVtYmVyIiwiU3RyaW5nIiwidW5kZWZpbmVkIiwidG9VcHBlckNhc2UiLCJpbnZhbGlkUGFyYW1zIiwiU3ltYm9sIiwibWFwIiwicGFyYW0iLCJtaXNzaW5nRGF0YSIsImZhbHN5VmFsdWVzIiwiTmFOIiwidmFsdWUiLCJpbnZhbGlkRGF0YSIsInRydXRoeVZhbHVlcyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7QUFDQTs7OztBQUNBOzs7O0FBRUEsZUFBSyx5SUFBTCxFQUFnSkEsS0FBSztBQUNuSixRQUFNQyxTQUFTO0FB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LGFBQUQsQ0FBbEIsQ0FBN0IsRUFBa0UsY0FBYUQsS0FBTSxFQUFyRjtBQUNELEdBVEQ7QUFVRCxDQTVCRDs7QUE4QkEsZUFBSyxrTUFBTCxFQUF5TTVELEtBQUs7QUFDNU0sUUFBTWdDLGNBQWM7QUFDbEJDLGdCQUFZLEVBRE07QUFFbEJDLGdCQUFZLEVBRk07QUFHbEJDLGdCQUFZO0FBSE0sR0FBcEI7QUFLQSxRQUFNQyxlQUFlLHVCQUFRSixXQUFSLENBQXJCOztBQUVBLFFBQU1LLGVBQWU7QUFDbkJDLGlCQUFhLEVBRE07QUFFbkJDLGlCQUFhO0FBQ1hqQyxlQUFTOEI7QUFERTtBQUZNLEdBQXJCO0FBTUEsUUFBTUksZ0JBQWdCLHVCQUFRSCxZQUFSLENBQXRCOztBQUVBLFFBQU15QixlQUFlLENBQUMsSUFBRCxFQUFPLGtCQUFQLEVBQTJCLENBQTNCLENBQXJCOztBQUVBQSxlQUFhUCxHQUFiLENBQWlCSyxTQUFTO0FBQ3hCLFVBQU1DLGNBQWM7QUFDbEJ2QixtQkFBYSxHQURLO0FBRWxCQyxtQkFBYTtBQUZLLEtBQXBCOztBQUtBLFVBQU1oQyxTQUFTaUMsY0FBY3FCLFdBQWQsQ0FBZjs7QUFFQTdELE1BQUVRLFNBQUYsQ0FBWUQsT0FBT1MsTUFBUCxHQUFnQnVCLFdBQTVCLEVBQXlDLEVBQXpDLEVBQThDLGNBQWFxQixLQUFNLEVBQWpFO0FBQ0QsR0FURDtBQVVELENBNUJEIiwiZmlsZSI6ImZhY3RvcnkudGVzdC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHRlc3QgfSBmcm9tICdhdmEnXG5pbXBvcnQgc3ViamVjdCBmcm9tICcuL2ZhY3RvcnknXG5pbXBvcnQgeyBwaWNrIH0gZnJvbSAnLi9jb21tb24nXG5cbnRlc3QoJ0dpdmVuIHNpbXBsZSBzY2hlbWEgYW5kIHZhbGlkRGF0YSwgd2hlbiBmYWN0b3J5IGlzIGNhbGxlZCwgc2hvdWxkIGNyZWF0ZSBwcm9wZXJ0eSBhY2Vzc29ycyB0byBhbGwgYW5kIG9ubHkgdGhlIGtleXMgZGVzY3JpYmVkIGluIHNjaGVtYScsIHQgPT4ge1xuICBjb25zdCBzY2hlbWEgPSB7XG4gICAgbXlQcm9wMToge30sXG4gICAgbXlQcm9wMjoge30sXG4gICAgbXlQcm9wMzoge31cbiAgfVxuXG4gIGNvbnN0IGRhdGEgPSB7XG4gICAgbXlQcm9wMTogJ2EnLFxuICAgIG15UHJvcDI6ICdiJyxcbiAgICBteVByb3AzOiAnYydcbiAgfVxuXG4gIGNvbnN0IGZhY3RvcnkgPSBzdWJqZWN0KHNjaGVtYSlcbiAgY29uc3QgcmVzdWx0ID0gZmFjdG9yeShkYXRhKVxuXG4gIHQuZGVlcEVxdWFsKE9iamVjdC5rZXlzKHJlc3VsdCksIE9iamVjdC5rZXlzKGRhdGEpKVxufSlcblxudGVzdCgnR2l2ZW4gc2NoZW1hIHdpdGggY29udGV4dHMgYW5kIHZhbGlkIGRhdGEsIHdoZW4gZmFjdG9yeSBpcyBjYWxsZWQsIHNob3VsZCBjcmVhdGUgcHJvcGVydHkgYWNlc3NvcnMgdG8gYWxsIGFuZCBvbmx5IHRoZSBrZXlzIGRlc2NyaWJlZCBpbiBzY2hlbWEnLCB0ID0+IHtcbiAgY29uc3Qgc2NoZW1hID0ge1xuICAgIG15UHJvcDE6IHt9LFxuICAgIG15UHJvcDI6IHt9LFxuICAgIG15UHJvcDM6IHt9LFxuXG4gICAgJGNvbnRleHRzOiB7XG4gICAgICBjb250ZXh0MToge30sXG4gICAgICBjb250ZXh0Mjoge31cbiAgICB9XG4gIH1cblxuICBjb25zdCBkYXRhID0ge1xuICAgIG15UHJvcDE6ICdhJyxcbiAgICBteVByb3AyOiAnYicsXG4gICAgbXlQcm9wMzogJ2MnXG4gIH1cblxuICBjb25zdCBmYWN0b3J5ID0gc3ViamVjdChzY2hlbWEpXG4gIGNvbnN0IHJlc3VsdCA9IGZhY3RvcnkoZGF0YSlcblxuICB0LmRlZXBFcXVhbChPYmplY3Qua2V5cyhyZXN1bHQpLCBPYmplY3Qua2V5cyhkYXRhKSlcbn0pXG5cbnRlc3QoJ0dpdmVuIHNpbXBsZSBzY2hlbWEgYW5kIG1pc3NpbmcgZGF0YSwgd2hlbiBmYWN0b3J5IGlzIGNhbGxlZCwgc2hvdWxkIGNyZWF0ZSBwcm9wZXJ0eSBhY2Vzc29ycyB0byBhbGwgYW5kIG9ubHkgdGhlIGtleXMgZGVzY3JpYmVkIGluIHNjaGVtYScsIHQgPT4ge1xuICBjb25zdCBzY2hlbWEgPSB7XG4gICAgbXlQcm9wMToge30sXG4gICAgbXlQcm9wMjoge30sXG4gICAgbXlQcm9wMzoge31cbiAgfVxuXG4gIGNvbnN0IGRhdGEgPSB7XG4gICAgbXlQcm9wMTogJ2EnLFxuICAgIG15UHJvcDI6ICdiJ1xuICB9XG5cbiAgY29uc3QgZmFjdG9yeSA9IHN1YmplY3Qoc2NoZW1hKVxuICBjb25zdCByZXN1bHQgPSBmYWN0b3J5KGRhdGEpXG5cbiAgdC5pcyhPYmplY3Qua2V5cyhyZXN1bHQpLmxlbmd0aCwgMylcbn0pXG5cbnRlc3QoJ0dpdmVuIHZhbGlkIGRhdGEsIHdoZW4gZmFjdG9yeSBpcyBjYWxsZWQsIHRoZW4gaXQgc2hvdWxkIGNyZWF0ZSBhbiBvYmplY3Qgd2l0aCBhbGwga2V5cyBmcm9tIHNjaGVtYScsIHQgPT4ge1xuICBjb25zdCBzY2hlbWEgPSB7XG4gICAgbXlQcm9wMToge30sXG4gICAgbXlQcm9wMjoge30sXG4gICAgbXlQcm9wMzoge31cbiAgfVxuICBjb25zdCBkYXRhID0ge1xuICAgIG15UHJvcDE6ICdhJyxcbiAgICBteVByb3AyOiAnYicsXG4gICAgbXlQcm9wMzogJ2MnXG4gIH1cbiAgY29uc3QgZmFjdG9yeSA9IHN1YmplY3Qoc2NoZW1hKVxuXG4gIGNvbnN0IHJlc3VsdCA9IGZhY3RvcnkoZGF0YSkudG9KU09OKClcblxuICB0LmRlZXBFcXVhbChyZXN1bHQsIGRhdGEpXG59KVxuXG50ZXN0KCdHaXZlbiB2YWxpZCBkYXRhLCB3aGVuIGZhY3RvcnkgaXMgY2FsbGVkLCB0aGVuIGl0IHNob3VsZCBjcmVhdGUgYW4gb2JqZWN0IHdpdGggYGNvbnN0cnV0b3JgIHByb3BlcnR5IHBvaW50aW5nIHRvIHRoZSBzYW1lIGZhY3RvcnknLCB0ID0+IHtcbiAgY29uc3Qgc2NoZW1hID0ge1xuICAgIG15UHJvcDE6IHt9LFxuICAgIG15UHJvcDI6IHt9LFxuICAgIG15UHJvcDM6IHt9XG4gIH1cbiAgY29uc3QgZGF0YSA9IHtcbiAgICBteVByb3AxOiAnYScsXG4gICAgbXlQcm9wMjogJ2InLFxuICAgIG15UHJvcDM6ICdjJ1xuICB9XG4gIGNvbnN0IGZhY3RvcnkgPSBzdWJqZWN0KHNjaGVtYSlcblxuICBjb25zdCByZXN1bHQgPSBmYWN0b3J5KGRhdGEpXG5cbiAgdC5pcyhyZXN1bHQuY29uc3RydWN0b3IsIGZhY3RvcnkpXG59KVxuXG50ZXN0KCdHaXZlbiB0d28gaWRlbnRpY2FsIHNjaGVtYXMsIHdoZW4gYW4gZW50aXR5IGZyb20gdGhlIGZpcnN0IG9uZSBpcyBjcmVhdGVkIGZyb20gYW4gZW50aXR5IGZyb20gdGhlIHNlY29uZCBvbmUsIHRoZW4gdGhlIGZhY3RvcnkgbXVzdCBhcHBseSBkdWNrIHR5cGluZyBhbmQgcmV0dXJuIGFuIG9iamVjdCBmcm9tIHRoZSBmaXJzdCB0eXBlJywgdCA9PiB7XG4gIGNvbnN0IHNjaGVtYTEgPSB7XG4gICAgbXlQcm9wMToge30sXG4gICAgbXlQcm9wMjoge30sXG4gICAgbXlQcm9wMzoge31cbiAgfVxuICBjb25zdCBzY2hlbWEyID0ge1xuICAgIG15UHJvcDE6IHt9LFxuICAgIG15UHJvcDI6IHt9LFxuICAgIG15UHJvcDM6IHt9XG4gIH1cblxuICBjb25zdCBkYXRhID0ge1xuICAgIG15UHJvcDE6ICdhJyxcbiAgICBteVByb3AyOiAnYicsXG4gICAgbXlQcm9wMzogJ2MnXG4gIH1cblxuICBjb25zdCBpbnN0YW5jZUZhY3RvcnkgPSBzdWJqZWN0KHNjaGVtYTEpXG4gIGNvbnN0IGFub3RoZXJJbnN0YW5jZUZhY3RvcnkgPSBzdWJqZWN0KHNjaGVtYTIpXG5cbiAgY29uc3QgcmVzdWx0ID0gaW5zdGFuY2VGYWN0b3J5KGFub3RoZXJJbnN0YW5jZUZhY3RvcnkoZGF0YSkpXG5cbiAgdC5pcyhyZXN1bHQuY29uc3RydWN0b3IsIGluc3RhbmNlRmFjdG9yeSlcbn0pXG5cbnRlc3QoJ0dpdmVuIHNjaGVtYSwgd2hlbiBmYWN0b3J5IGlzIGNhbGxlZCwgdGhlbiBpdCBzaG91bGQgcmV0dXJuIGFuIG9iamVjdCB3aGljaCBpcyBub3QgYGluc3RuYWNlb2ZgIHRoZSBmYWN0b3J5JywgdCA9PiB7XG4gIGNvbnN0IHNjaGVtYSA9IHtcbiAgICBteVByb3AxOiB7fSxcbiAgICBteVByb3AyOiB7fSxcbiAgICBteVByb3AzOiB7fVxuICB9XG5cbiAgY29uc3QgZGF0YSA9IHtcbiAgICBteVByb3AxOiAnYScsXG4gICAgbXlQcm9wMjogJ2InLFxuICAgIG15UHJvcDM6ICdjJ1xuICB9XG5cbiAgY29uc3QgZmFjdG9yeSA9IHN1YmplY3Qoc2NoZW1hKVxuICBjb25zdCBpbnN0YW5jZSA9IGZhY3RvcnkoZGF0YSlcblxuICBjb25zdCBlcnJvciA9IHQudGhyb3dzKCgpID0+IGluc3RhbmNlIGluc3RhbmNlb2YgZmFjdG9yeSlcbiAgdC5yZWdleChlcnJvci5tZXNzYWdlLCAvZnVuY3Rpb24gaGFzIG5vbi1vYmplY3QgcHJvdG90eXBlL2kpXG59KVxuXG50ZXN0KCdHaXZlbiBhbHJlYWR5IGluc3RhbnRpYXRlZCBlbnRpdHksIHdoZW4gZmFjdG9yeSBpcyBjYWxsZWQsIHRoZW4gaXQgc2hvdWxkIGNyZWF0ZSBhIGNvcHkgb2YgdGhlIG9yaWdpbmFsIGRhdGEnLCB0ID0+IHtcbiAgY29uc3Qgc2NoZW1hID0ge1xuICAgIG15UHJvcDE6IHt9LFxuICAgIG15UHJvcDI6IHt9LFxuICAgIG15UHJvcDM6IHt9XG4gIH1cbiAgY29uc3QgZGF0YSA9IHtcbiAgICBteVByb3AxOiAnYScsXG4gICAgbXlQcm9wMjogJ2InLFxuICAgIG15UHJvcDM6ICdjJ1xuICB9XG4gIGNvbnN0IGZhY3RvcnkgPSBzdWJqZWN0KHNjaGVtYSlcblxuICBjb25zdCBmaXJzdEluc3RhbmNlID0gZmFjdG9yeShkYXRhKVxuXG4gIGNvbnN0IHNlY29uZEluc3RhbmNlID0gZmFjdG9yeShmaXJzdEluc3RhbmNlKVxuXG4gIHQubm90KHNlY29uZEluc3RhbmNlLCBmaXJzdEluc3RhbmNlKVxuICB0LmRlZXBFcXVhbChzZWNvbmRJbnN0YW5jZSwgZmlyc3RJbnN0YW5jZSlcbn0pXG5cbnRlc3QoJ0dpdmVuIGRhdGEgd2l0aCBleHRyYSBmaWVsZHMsIHdoZW4gZmFjdG9yeSBpcyBjYWxsZWQsIHRoZW4gaXQgc2hvdWxkIGNyZWF0ZSBhbiBvYmplY3Qgd2l0aCBvbmx5IHRoZSBrZXlzIGZyb20gc2NoZW1hLCBkcm9wcGluZyB0aGUgdW5zcGVjaWZpZWQgb25lcycsIHQgPT4ge1xuICBjb25zdCBzY2hlbWEgPSB7XG4gICAgbXlQcm9wMToge30sXG4gICAgbXlQcm9wMjoge31cbiAgfVxuICBjb25zdCBkYXRhID0ge1xuICAgIG15UHJvcDE6ICdhJyxcbiAgICBteVByb3AyOiAnYicsXG4gICAgdW5lc3BlY2lmaWVkRmllbGQxOiAnYydcbiAgfVxuICBjb25zdCBleHBlY3RlZCA9IHtcbiAgICBteVByb3AxOiAnYScsXG4gICAgbXlQcm9wMjogJ2InXG4gIH1cbiAgY29uc3QgZmFjdG9yeSA9IHN1YmplY3Qoc2NoZW1hKVxuXG4gIGNvbnN0IHJlc3VsdCA9IGZhY3RvcnkoZGF0YSkudG9KU09OKClcblxuICB0LmRlZXBFcXVhbChyZXN1bHQsIGV4cGVjdGVkKVxufSlcblxudGVzdCgnR2l2ZW4gdmFsaWQgZGF0YSwgd2hlbiBmYWN0b3J5IGlzIGNhbGxlZCwgdGhlbiBpdCBzaG91bGQgY3JlYXRlIGFuIG9iamVjdCB3aXRoIGFsbCBrZXlzIGZyb20gc2NoZW1hJywgdCA9PiB7XG4gIGNvbnN0IHNjaGVtYSA9IHtcbiAgICBteVByb3AxOiB7fSxcbiAgICBteVByb3AyOiB7fSxcbiAgICBteVByb3AzOiB7fVxuICB9XG4gIGNvbnN0IGRhdGEgPSB7XG4gICAgbXlQcm9wMTogJ2EnLFxuICAgIG15UHJvcDI6ICdiJyxcbiAgICBteVByb3AzOiAnYydcbiAgfVxuICBjb25zdCBmYWN0b3J5ID0gc3ViamVjdChzY2hlbWEpXG5cbiAgY29uc3QgcmVzdWx0ID0gZmFjdG9yeShkYXRhKS50b0pTT04oKVxuXG4gIHQuZGVlcEVxdWFsKHJlc3VsdCwgZGF0YSlcbn0pXG5cbnRlc3QoJ0dpdmVuIGRhdGEgd2l0aCBleHRyYSBmaWVsZHMsIHdoZW4gZmFjdG9yeSBpcyBjYWxsZWQsIHRoZW4gaXQgc2hvdWxkIGNyZWF0ZSBhbiBvYmplY3Qgd2l0aCBvbmx5IHRoZSBrZXlzIGZyb20gc2NoZW1hLCBkcm9wcGluZyB0aGUgdW5zcGVjaWZpZWQgb25lcycsIHQgPT4ge1xuICBjb25zdCBzY2hlbWEgPSB7XG4gICAgbXlQcm9wMToge30sXG4gICAgbXlQcm9wMjoge31cbiAgfVxuICBjb25zdCBkYXRhID0ge1xuICAgIG15UHJvcDE6ICdhJyxcbiAgICBteVByb3AyOiAnYicsXG4gICAgdW5lc3BlY2lmaWVkRmllbGQxOiAnYydcbiAgfVxuICBjb25zdCBleHBlY3RlZCA9IHtcbiAgICBteVByb3AxOiAnYScsXG4gICAgbXlQcm9wMjogJ2InXG4gIH1cbiAgY29uc3QgZmFjdG9yeSA9IHN1YmplY3Qoc2NoZW1hKVxuXG4gIGNvbnN0IHJlc3VsdCA9IGZhY3RvcnkoZGF0YSkudG9KU09OKClcblxuICB0LmRlZXBFcXVhbChyZXN1bHQsIGV4cGVjdGVkKVxufSlcblxudGVzdCgnR2l2ZW4gdmFsaWQgZGF0YSB3aXRoIG5lc3RlZCBlbnRpdHksIHdoZW4gZmFjdG9yeSBpcyBjYWxsZWQgZm9yIHBhcmVudCBlbnRpdHksIHRoZW4gaXQgc2hvdWxkIGNyZWF0ZSBhbiBvYmplY3QgcmVmZXJlbmNpbmcgdGhlIGNoaWxkIGVudGl0eScsIHQgPT4ge1xuICBjb25zdCBjaGlsZFNjaGVtYSA9IHtcbiAgICBjaGlsZFByb3AxOiB7fSxcbiAgICBjaGlsZFByb3AyOiB7fSxcbiAgICBjaGlsZFByb3AzOiB7fVxuICB9XG4gIGNvbnN0IGNoaWxkRmFjdG9yeSA9IHN1YmplY3QoY2hpbGRTY2hlbWEpXG5cbiAgY29uc3QgcGFyZW50U2NoZW1hID0ge1xuICAgIHBhcmVudFByb3AxOiB7fSxcbiAgICBjaGlsZEVudGl0eToge1xuICAgICAgZmFjdG9yeTogY2hpbGRGYWN0b3J5XG4gICAgfVxuICB9XG4gIGNvbnN0IHBhcmVudEZhY3RvcnkgPSBzdWJqZWN0KHBhcmVudFNjaGVtYSlcblxuICBjb25zdCB2YWxpZERhdGEgPSB7XG4gICAgcGFyZW50UHJvcDE6ICdhJyxcbiAgICBjaGlsZEVudGl0eToge1xuICAgICAgY2hpbGRQcm9wMTogJ2InLFxuICAgICAgY2hpbGRQcm9wMjogJ2MnLFxuICAgICAgY2hpbGRQcm9wMzogJ2QnXG4gICAgfVxuICB9XG5cbiAgY29uc3QgcmVzdWx0ID0gcGFyZW50RmFjdG9yeSh2YWxpZERhdGEpXG5cbiAgdC5kZWVwRXF1YWwocmVzdWx0LmNoaWxkRW50aXR5LCBjaGlsZEZhY3RvcnkodmFsaWREYXRhLmNoaWxkRW50aXR5KSlcbn0pXG5cbnRlc3QoJ0dpdmVuIG5lc3RlZCBjaGlsZCBkYXRhIHdpdGggZXh0cmEgcHJvcGVydGllcywgd2hlbiBmYWN0b3J5IGlzIGNhbGxlZCBmb3IgcGFyZW50IGVudGl0eSwgdGhlbiBpdCBzaG91bGQgY3JlYXRlIGFuIG9iamVjdCByZWZlcmVuY2luZyB0aGUgY2hpbGQgZW50aXR5IGV4Y2x1ZGluZyB0aGUgZXh0cmEgcHJvcGVydGllcycsIHQgPT4ge1xuICBjb25zdCBjaGlsZFNjaGVtYSA9IHtcbiAgICBjaGlsZFByb3AxOiB7fVxuICB9XG4gIGNvbnN0IGNoaWxkRmFjdG9yeSA9IHN1YmplY3QoY2hpbGRTY2hlbWEpXG5cbiAgY29uc3QgcGFyZW50U2NoZW1hID0ge1xuICAgIGNoaWxkRW50aXR5OiB7XG4gICAgICBmYWN0b3J5OiBjaGlsZEZhY3RvcnlcbiAgICB9XG4gIH1cbiAgY29uc3QgcGFyZW50RmFjdG9yeSA9IHN1YmplY3QocGFyZW50U2NoZW1hKVxuXG4gIGNvbnN0IGV4dHJhUHJvcGVydGllc09uTmVzdGVkQ2hpbGREYXRhID0ge1xuICAgIGNoaWxkRW50aXR5OiB7XG4gICAgICBjaGlsZFByb3AxOiAnYicsXG4gICAgICBjaGlsZFByb3AyOiAnYydcbiAgICB9XG4gIH1cblxuICBjb25zdCBleHBlY3RlZCA9IHtcbiAgICBjaGlsZEVudGl0eToge1xuICAgICAgY2hpbGRQcm9wMTogJ2InXG4gICAgfVxuICB9XG5cbiAgY29uc3QgcmVzdWx0ID0gcGFyZW50RmFjdG9yeShleHRyYVByb3BlcnRpZXNPbk5lc3RlZENoaWxkRGF0YSkudG9KU09OKClcbiAgdC5kZWVwRXF1YWwocmVzdWx0LCBleHBlY3RlZClcbn0pXG5cbnRlc3QoJ0dpdmVuIG1pc3NpbmcgbmVzdGVkIGNoaWxkIGRhdGEsIHdoZW4gZmFjdG9yeSBpcyBjYWxsZWQgZm9yIHBhcmVudCBlbnRpdHksIHRoZW4gaXQgc2hvdWxkIGNyZWF0ZSBhbiBvYmplY3QgdGhhdCBkb2VzIG5vdCBjb250YWluIHRoZSBwcm9wZXJ0eSByZWxhdGVkIHRvIHRoZSBjaGlsZCBlbnRpdHknLCB0ID0+IHtcbiAgY29uc3QgY2hpbGRTY2hlbWEgPSB7XG4gICAgY2hpbGRQcm9wMToge31cbiAgfVxuICBjb25zdCBjaGlsZEZhY3RvcnkgPSBzdWJqZWN0KGNoaWxkU2NoZW1hKVxuXG4gIGNvbnN0IHBhcmVudFNjaGVtYSA9IHtcbiAgICBwcm9wMToge30sXG4gICAgY2hpbGRFbnRpdHk6IHtcbiAgICAgIGZhY3Rvcnk6IGNoaWxkRmFjdG9yeVxuICAgIH1cbiAgfVxuICBjb25zdCBwYXJlbnRGYWN0b3J5ID0gc3ViamVjdChwYXJlbnRTY2hlbWEpXG5cbiAgY29uc3QgbWlzc2luZ0NoaWxkRW50aXR5RGF0YSA9IHtcbiAgICBwcm9wMTogJ2EnXG4gIH1cblxuICBjb25zdCBleHBlY3RlZCA9IHtcbiAgICBwcm9wMTogJ2EnXG4gIH1cblxuICBjb25zdCByZXN1bHQgPSBwYXJlbnRGYWN0b3J5KG1pc3NpbmdDaGlsZEVudGl0eURhdGEpLnRvSlNPTigpXG4gIHQuZGVlcEVxdWFsKHJlc3VsdCwgZXhwZWN0ZWQpXG59KVxuXG50ZXN0KCdHaXZlbiB2YWxpZCBkYXRhIHdpdGggbmVzdGVkIGVudGl0eSwgd2hlbiBmYWN0b3J5IGlzIGNhbGxlZCBmb3IgcGFyZW50IGVudGl0eSB3aXRoIGRhdGEgdGhhdCBpcyBhbHJlYWR5IGFuIGluc3RhbmNlIG9mIGNoaWxkLCB0aGVuIGl0IHNob3VsZCBjcmVhdGUgYW4gb2JqZWN0IHJlZmVyZW5jaW5nIHRoZSBjaGlsZCBlbnRpdHknLCB0ID0+IHtcbiAgY29uc3QgY2hpbGRTY2hlbWEgPSB7XG4gICAgY2hpbGRQcm9wMToge30sXG4gICAgY2hpbGRQcm9wMjoge30sXG4gICAgY2hpbGRQcm9wMzoge31cbiAgfVxuICBjb25zdCBjaGlsZEZhY3RvcnkgPSBzdWJqZWN0KGNoaWxkU2NoZW1hKVxuXG4gIGNvbnN0IHBhcmVudFNjaGVtYSA9IHtcbiAgICBwYXJlbnRQcm9wMToge30sXG4gICAgY2hpbGRFbnRpdHk6IHtcbiAgICAgIGZhY3Rvcnk6IGNoaWxkRmFjdG9yeVxuICAgIH1cbiAgfVxuICBjb25zdCBwYXJlbnRGYWN0b3J5ID0gc3ViamVjdChwYXJlbnRTY2hlbWEpXG5cbiAgY29uc3QgdmFsaWREYXRhID0ge1xuICAgIHBhcmVudFByb3AxOiAnYScsXG4gICAgY2hpbGRFbnRpdHk6IGNoaWxkRmFjdG9yeSh7XG4gICAgICBjaGlsZFByb3AxOiAnYicsXG4gICAgICBjaGlsZFByb3AyOiAnYycsXG4gICAgICBjaGlsZFByb3AzOiAnZCdcbiAgICB9KVxuICB9XG5cbiAgY29uc3QgcmVzdWx0ID0gcGFyZW50RmFjdG9yeSh2YWxpZERhdGEpXG5cbiAgdC5kZWVwRXF1YWwocmVzdWx0LmNoaWxkRW50aXR5LCBjaGlsZEZhY3RvcnkodmFsaWREYXRhLmNoaWxkRW50aXR5KSlcbn0pXG5cbnRlc3QoJ0dpdmVuIGFscmVhZHkgaW5zdGFudGlhdGVkIGNvbXBvc2l0ZSBlbnRpdHksIHdoZW4gZmFjdG9yeSBpcyBjYWxsZWQsIHRoZW4gaXQgc2hvdWxkIGNyZWF0ZSBhIGNvcHkgb2YgdGhlIG9yaWdpbmFsIG5lc3RlZCBlbnRpdHknLCB0ID0+IHtcbiAgY29uc3QgY2hpbGRTY2hlbWEgPSB7XG4gICAgY2hpbGRQcm9wMToge30sXG4gICAgY2hpbGRQcm9wMjoge30sXG4gICAgY2hpbGRQcm9wMzoge31cbiAgfVxuICBjb25zdCBjaGlsZEZhY3RvcnkgPSBzdWJqZWN0KGNoaWxkU2NoZW1hKVxuXG4gIGNvbnN0IHBhcmVudFNjaGVtYSA9IHtcbiAgICBwYXJlbnRQcm9wMToge30sXG4gICAgY2hpbGRFbnRpdHk6IHtcbiAgICAgIGZhY3Rvcnk6IGNoaWxkRmFjdG9yeVxuICAgIH1cbiAgfVxuICBjb25zdCBwYXJlbnRGYWN0b3J5ID0gc3ViamVjdChwYXJlbnRTY2hlbWEpXG5cbiAgY29uc3QgdmFsaWREYXRhID0ge1xuICAgIHBhcmVudFByb3AxOiAnYScsXG4gICAgY2hpbGRFbnRpdHk6IHtcbiAgICAgIGNoaWxkUHJvcDE6ICdiJyxcbiAgICAgIGNoaWxkUHJvcDI6ICdjJyxcbiAgICAgIGNoaWxkUHJvcDM6ICdkJ1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGZpcnN0SW5zdGFuY2UgPSBwYXJlbnRGYWN0b3J5KHZhbGlkRGF0YSlcblxuICBjb25zdCBzZWNvbmRJbnN0YW5jZSA9IHBhcmVudEZhY3RvcnkoZmlyc3RJbnN0YW5jZSlcblxuICB0Lm5vdChzZWNvbmRJbnN0YW5jZS5jaGlsZEVudGl0eSwgZmlyc3RJbnN0YW5jZS5jaGlsZEVudGl0eSlcbiAgdC5kZWVwRXF1YWwoc2Vjb25kSW5zdGFuY2UuY2hpbGRFbnRpdHksIGZpcnN0SW5zdGFuY2UuY2hpbGRFbnRpdHkpXG59KVxuXG50ZXN0KCdHaXZlbiBzY2hlbWEgd2l0aCAkbWV0aG9kcywgd2hlbiBmYWN0b3J5IGlzIGNhbGxlZCwgdGhlbiBpdCBzaG91bGQgY3JlYXRlIGFuIG9iamVjdCB3aXRoIGFsbCBtZXRob2RzIGZyb20gc2NoZW1hJywgdCA9PiB7XG4gIGNvbnN0IHNjaGVtYSA9IHtcbiAgICBteVByb3AxOiB7fSxcbiAgICBteVByb3AyOiB7fSxcbiAgICBteVByb3AzOiB7fSxcbiAgICAkbWV0aG9kczoge1xuICAgICAgbXlNZXRob2QgKCkge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy5teVByb3AxfSwgJHt0aGlzLm15UHJvcDJ9LCAke3RoaXMubXlQcm9wM31gXG4gICAgICB9XG4gICAgfVxuICB9XG4gIGNvbnN0IGRhdGEgPSB7XG4gICAgbXlQcm9wMTogJ2EnLFxuICAgIG15UHJvcDI6ICdiJyxcbiAgICBteVByb3AzOiAnYydcbiAgfVxuICBjb25zdCBmYWN0b3J5ID0gc3ViamVjdChzY2hlbWEpXG5cbiAgY29uc3QgcmVzdWx0ID0gZmFjdG9yeShkYXRhKS5teU1ldGhvZCgpXG5cbiAgdC5kZWVwRXF1YWwocmVzdWx0LCAnYSwgYiwgYycpXG59KVxuXG50ZXN0KCdHaXZlbiBubyBkYXRhLCB3aGVuIGZhY3RvcnkgaXMgY2FsbGVkLCB0aGVuIGl0IHNob3VsZCBwcm9wZXJseSByZXR1cm4gYW4gZW1wdHkgZW50aXR5JywgdCA9PiB7XG4gIGNvbnN0IHNjaGVtYSA9IHtcbiAgICBteVByb3AxOiB7fSxcbiAgICBteVByb3AyOiB7fSxcbiAgICBteVByb3AzOiB7fVxuICB9XG5cbiAgY29uc3QgZmFjdG9yeSA9IHN1YmplY3Qoc2NoZW1hKVxuXG4gIGNvbnN0IHJlc3VsdCA9IGZhY3RvcnkoKVxuXG4gIHQuZGVlcEVxdWFsKHJlc3VsdC50b0pTT04oKSwge30pXG59KVxuXG50ZXN0KCdHaXZlbiBkYXRhIHRoYXQgZG9lcyBub3QgY29udGFpbiBhbnkgdmFsaWQgcHJvcGVydHksIHdoZW4gZmFjdG9yeSBpcyBjYWxsZWQsIHRoZW4gaXQgc2hvdWxkIHJldHVybiBhbiBlbXB0eSBlbnRpdHknLCB0ID0+IHtcbiAgY29uc3Qgc2NoZW1hID0ge1xuICAgIG15UHJvcDE6IHt9LFxuICAgIG15UHJvcDI6IHt9LFxuICAgIG15UHJvcDM6IHt9XG4gIH1cblxuICBjb25zdCBmYWN0b3J5ID0gc3ViamVjdChzY2hlbWEpXG5cbiAgY29uc3QgcmVzdWx0ID0gZmFjdG9yeSh7XG4gICAgdW5leGlzdGVudFByb3A6ICd4J1xuICB9KVxuXG4gIHQuZGVlcEVxdWFsKHJlc3VsdC50b0pTT04oKSwge30pXG59KVxuXG50ZXN0KCdHaXZlbiBzY2hlbWEgd2l0aCBwcm9wZXJ0eSBgZmFjdG9yeWAgYXMgTnVtYmVyLCB3aGVuIGZhY3RvcnkgaXMgY2FsbGVkLCB0aGVuIGl0IHNob3VsZCByZXR1cm4gYW4gZW50aXR5IHRoYXQgY29udGFpbnMgdGhlIHJlZmVycmVkIHByb3BlcnR5JywgdCA9PiB7XG4gIGNvbnN0IHNjaGVtYSA9IHtcbiAgICBteVByb3AxOiB7XG4gICAgICBmYXRvcnk6IE51bWJlclxuICAgIH0sXG4gICAgbXlQcm9wMjoge31cbiAgfVxuXG4gIGNvbnN0IGZhY3RvcnkgPSBzdWJqZWN0KHNjaGVtYSlcblxuICBjb25zdCBkYXRhID0ge1xuICAgIG15UHJvcDI6ICcyMDAnXG4gIH1cblxuICBjb25zdCByZXN1bHQgPSBmYWN0b3J5KGRhdGEpXG5cbiAgdC5kZWVwRXF1YWwocmVzdWx0LnRvSlNPTigpLCBkYXRhKVxufSlcblxudGVzdCgnR2l2ZW4gc2NoZW1hIHdpdGggcHJvcGVydHkgYGZhY3RvcnlgLCB3aGVuIGZhY3RvcnkgaXMgY2FsbGVkIHdpdGggbWlzc2luZyBkYXRhIGZvciBzdWNoIHByb3BlcnR5LCB0aGVuIGl0IHNob3VsZCByZXR1cm4gYW4gZW50aXR5IHRoYXQgZG9lcyBub3QgY29udGFpbiB0aGUgcmVmZXJyZWQgcHJvcGVydHknLCB0ID0+IHtcbiAgY29uc3Qgc2NoZW1hID0ge1xuICAgIG15UHJvcDE6IHtcbiAgICAgIGZhdG9yeTogU3RyaW5nXG4gICAgfSxcbiAgICBteVByb3AyOiB7fVxuICB9XG5cbiAgY29uc3QgZmFjdG9yeSA9IHN1YmplY3Qoc2NoZW1hKVxuXG4gIGNvbnN0IGRhdGEgPSB7XG4gICAgbXlQcm9wMjogJ2EnXG4gIH1cblxuICBjb25zdCByZXN1bHQgPSBmYWN0b3J5KGRhdGEpXG5cbiAgdC5kZWVwRXF1YWwocmVzdWx0LnRvSlNPTigpLCBkYXRhKVxuICB0LmlzKHJlc3VsdC5teVByb3AxLCB1bmRlZmluZWQpXG59KVxuXG50ZXN0KCdHaXZlbiBkYXRhIHRoYXQgaXMgbm90IGFuIG9iamVjdCwgd2hlbiBmYWN0b3J5IGlzIGNhbGxlZCwgdGhlbiBpdCBzaG91bGQgcmV0dXJuIGFuIGVtcHR5IGVudGl0eScsIHQgPT4ge1xuICBjb25zdCBzY2hlbWEgPSB7XG4gICAgbXlQcm9wMToge30sXG4gICAgbXlQcm9wMjoge30sXG4gICAgbXlQcm9wMzoge30sXG4gICAgdG9VcHBlckNhc2U6IHt9LCAvLyB3aWxsIGl0IGJsb3cgdXAgZm9yIHN0cmluZz9cbiAgICBsZW5ndGg6IHt9IC8vIHdpbGwgaXQgYmxvdyB1cCBmb3IgYXJyYXlzP1xuICB9XG5cbiAgY29uc3QgZmFjdG9yeSA9IHN1YmplY3Qoc2NoZW1hKVxuXG4gIGNvbnN0IGludmFsaWRQYXJhbXMgPSBbXG4gICAgbnVsbCxcbiAgICAnc29tZSBzdHJpbmcnLFxuICAgIFtdLFxuICAgIFsnbm9uLWVtcHR5IGFycmF5J10sXG4gICAgMTIzMTIzLFxuICAgIFN5bWJvbCgnZm9vJyksXG4gICAgL3JlZ2V4L1xuICBdXG5cbiAgaW52YWxpZFBhcmFtcy5tYXAocGFyYW0gPT4ge1xuICAgIHQuZGVlcEVxdWFsKGZhY3RvcnkocGFyYW0pLnRvSlNPTigpLCB7fSlcbiAgfSlcbn0pXG5cbnRlc3QoJ0dpdmVuIGRhdGEgd2l0aCBubyB2YWx1ZSBmb3IgbmVzdGVkIGVudGl0eSwgd2hlbiBmYWN0b3J5IGlzIGNhbGxlZCBmb3IgcGFyZW50IGVudGl0eSwgdGhlbiB0aGUgcmVzdWx0aW5nIG9iamVjdCBzaG91bGQgbm90IGhhdmUgYSBwcm9wZXJ0eSBmb3Igc3VjaCBuZXN0ZWQgZW50aXR5JywgdCA9PiB7XG4gIGNvbnN0IGNoaWxkU2NoZW1hID0ge1xuICAgIGNoaWxkUHJvcDE6IHt9LFxuICAgIGNoaWxkUHJvcDI6IHt9LFxuICAgIGNoaWxkUHJvcDM6IHt9XG4gIH1cbiAgY29uc3QgY2hpbGRGYWN0b3J5ID0gc3ViamVjdChjaGlsZFNjaGVtYSlcblxuICBjb25zdCBwYXJlbnRTY2hlbWEgPSB7XG4gICAgcGFyZW50UHJvcDE6IHt9LFxuICAgIGNoaWxkRW50aXR5OiB7XG4gICAgICBmYWN0b3J5OiBjaGlsZEZhY3RvcnlcbiAgICB9XG4gIH1cbiAgY29uc3QgcGFyZW50RmFjdG9yeSA9IHN1YmplY3QocGFyZW50U2NoZW1hKVxuXG4gIGNvbnN0IG1pc3NpbmdEYXRhID0ge1xuICAgIHBhcmVudFByb3AxOiAnYSdcbiAgfVxuXG4gIGNvbnN0IHJlc3VsdCA9IHBhcmVudEZhY3RvcnkobWlzc2luZ0RhdGEpXG5cbiAgdC5kZWVwRXF1YWwocmVzdWx0LnRvSlNPTigpLCBtaXNzaW5nRGF0YSlcbn0pXG5cbnRlc3QoJ0dpdmVuIGRhdGEgd2l0aCBmYWxzeSB2YWx1ZSBmb3IgbmVzdGVkIGVudGl0eSwgd2hlbiBmYWN0b3J5IGlzIGNhbGxlZCBmb3IgcGFyZW50IGVudGl0eSwgdGhlbiB0aGUgcmVzdWx0aW5nIG9iamVjdCBzaG91bGQgbm90IGhhdmUgYSBwcm9wZXJ0eSBmb3Igc3VjaCBuZXN0ZWQgZW50aXR5JywgdCA9PiB7XG4gIGNvbnN0IGNoaWxkU2NoZW1hID0ge1xuICAgIGNoaWxkUHJvcDE6IHt9LFxuICAgIGNoaWxkUHJvcDI6IHt9LFxuICAgIGNoaWxkUHJvcDM6IHt9XG4gIH1cbiAgY29uc3QgY2hpbGRGYWN0b3J5ID0gc3ViamVjdChjaGlsZFNjaGVtYSlcblxuICBjb25zdCBwYXJlbnRTY2hlbWEgPSB7XG4gICAgcGFyZW50UHJvcDE6IHt9LFxuICAgIGNoaWxkRW50aXR5OiB7XG4gICAgICBmYWN0b3J5OiBjaGlsZEZhY3RvcnlcbiAgICB9XG4gIH1cbiAgY29uc3QgcGFyZW50RmFjdG9yeSA9IHN1YmplY3QocGFyZW50U2NoZW1hKVxuXG4gIGNvbnN0IGZhbHN5VmFsdWVzID0gW3VuZGVmaW5lZCwgbnVsbCwgZmFsc2UsICcnLCAwLCBOYU5dXG5cbiAgZmFsc3lWYWx1ZXMubWFwKHZhbHVlID0+IHtcbiAgICBjb25zdCBpbnZhbGlkRGF0YSA9IHtcbiAgICAgIHBhcmVudFByb3AxOiAnYScsXG4gICAgICBjaGlsZEVudGl0eTogbnVsbFxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IHBhcmVudEZhY3RvcnkoaW52YWxpZERhdGEpXG5cbiAgICB0LmRlZXBFcXVhbChyZXN1bHQudG9KU09OKCksIHBpY2soaW52YWxpZERhdGEsIFsncGFyZW50UHJvcDEnXSksIGBGYWlsZWQgZm9yICR7dmFsdWV9YClcbiAgfSlcbn0pXG5cbnRlc3QoJ0dpdmVuIGRhdGEgd2l0aCB0cnV0aHkgbm9uLW9iamVjdCB2YWx1ZSBmb3IgbmVzdGVkIGVudGl0eSwgd2hlbiBmYWN0b3J5IGlzIGNhbGxlZCBmb3IgcGFyZW50IGVudGl0eSwgdGhlbiB0aGUgcmVzdWx0aW5nIG9iamVjdCBzaG91bGQgaGF2ZSBhIHByb3BlcnR5IHdpdGggYW4gZW1wdHkgdmFsdWUgZm9yIHN1Y2ggbmVzdGVkIGVudGl0eScsIHQgPT4ge1xuICBjb25zdCBjaGlsZFNjaGVtYSA9IHtcbiAgICBjaGlsZFByb3AxOiB7fSxcbiAgICBjaGlsZFByb3AyOiB7fSxcbiAgICBjaGlsZFByb3AzOiB7fVxuICB9XG4gIGNvbnN0IGNoaWxkRmFjdG9yeSA9IHN1YmplY3QoY2hpbGRTY2hlbWEpXG5cbiAgY29uc3QgcGFyZW50U2NoZW1hID0ge1xuICAgIHBhcmVudFByb3AxOiB7fSxcbiAgICBjaGlsZEVudGl0eToge1xuICAgICAgZmFjdG9yeTogY2hpbGRGYWN0b3J5XG4gICAgfVxuICB9XG4gIGNvbnN0IHBhcmVudEZhY3RvcnkgPSBzdWJqZWN0KHBhcmVudFNjaGVtYSlcblxuICBjb25zdCB0cnV0aHlWYWx1ZXMgPSBbdHJ1ZSwgJ25vbi1lbXB0eSBzdHJpbmcnLCAxXVxuXG4gIHRydXRoeVZhbHVlcy5tYXAodmFsdWUgPT4ge1xuICAgIGNvbnN0IGludmFsaWREYXRhID0ge1xuICAgICAgcGFyZW50UHJvcDE6ICdhJyxcbiAgICAgIGNoaWxkRW50aXR5OiB0cnVlXG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0ID0gcGFyZW50RmFjdG9yeShpbnZhbGlkRGF0YSlcblxuICAgIHQuZGVlcEVxdWFsKHJlc3VsdC50b0pTT04oKS5jaGlsZEVudGl0eSwge30sIGBGYWlsZWQgZm9yICR7dmFsdWV9YClcbiAgfSlcbn0pXG4iXX0=