@decaf-ts/db-decorators
Version:
Agnostic database decorators and repository
127 lines (125 loc) • 20.1 kB
JavaScript
import { ModelErrorDefinition, ModelKeys, ReservedModels, sf, Validation, ValidationKeys, } from "@decaf-ts/decorator-validation";
import { Reflection } from "@decaf-ts/reflection";
import { UpdateValidationKeys } from "../validation";
import { findModelId } from "../identity";
/**
* @summary Validates the update of a model
*
* @param {T} oldModel
* @param {T} newModel
* @param {string[]} [exceptions]
*
* @function validateCompare
* @return {ModelErrorDefinition | undefined}
*
* @memberOf module:db-decorators.Model
*/
export function validateCompare(oldModel, newModel, ...exceptions) {
const decoratedProperties = [];
for (const prop in newModel)
if (Object.prototype.hasOwnProperty.call(newModel, prop) &&
exceptions.indexOf(prop) === -1)
decoratedProperties.push(Reflection.getPropertyDecorators(UpdateValidationKeys.REFLECT, newModel, prop));
let result = undefined;
for (const decoratedProperty of decoratedProperties) {
const { prop, decorators } = decoratedProperty;
decorators.shift(); // remove the design:type decorator, since the type will already be checked
if (!decorators || !decorators.length)
continue;
let errs = undefined;
for (const decorator of decorators) {
const validator = Validation.get(decorator.key);
if (!validator) {
console.error(`Could not find Matching validator for ${decorator.key} for property ${String(decoratedProperty.prop)}`);
continue;
}
const err = validator.updateHasErrors(newModel[prop.toString()], oldModel[prop.toString()], ...Object.values(decorator.props));
if (err) {
errs = errs || {};
errs[decorator.key] = err;
}
}
if (errs) {
result = result || {};
result[decoratedProperty.prop.toString()] = errs;
}
}
// tests nested classes
for (const prop of Object.keys(newModel).filter((k) => {
if (exceptions.includes(k))
return false;
return !result || !result[k];
})) {
let err;
// if a nested Model
const allDecorators = Reflection.getPropertyDecorators(ValidationKeys.REFLECT, newModel, prop).decorators;
const decorators = Reflection.getPropertyDecorators(ValidationKeys.REFLECT, newModel, prop).decorators.filter((d) => [ModelKeys.TYPE, ValidationKeys.TYPE].indexOf(d.key) !== -1);
if (!decorators || !decorators.length)
continue;
const dec = decorators.pop();
const clazz = dec.props.name
? [dec.props.name]
: Array.isArray(dec.props.customTypes)
? dec.props.customTypes
: [dec.props.customTypes];
const reserved = Object.values(ReservedModels).map((v) => v.toLowerCase());
for (const c of clazz) {
if (reserved.indexOf(c.toLowerCase()) === -1) {
switch (c) {
case Array.name:
case Set.name:
if (allDecorators.length) {
const listDec = allDecorators.find((d) => d.key === ValidationKeys.LIST);
if (listDec) {
let currentList, oldList;
switch (c) {
case Array.name:
currentList = newModel[prop];
oldList = oldModel[prop];
break;
case Set.name:
currentList = newModel[prop].values();
oldList = oldModel[prop].values();
break;
default:
throw new Error(`Invalid attribute type ${c}`);
}
err = currentList
.map((v) => {
const id = findModelId(v, true);
if (!id)
return "Failed to find model id";
const oldModel = oldList.find((el) => id === findModelId(el, true));
if (!oldModel)
return; // nothing to compare with
return v.hasErrors(oldModel);
})
.filter((e) => !!e);
if (!err?.length) {
// if the result is an empty list...
err = undefined;
}
}
}
break;
default:
try {
if (newModel[prop] &&
oldModel[prop])
err = newModel[prop].hasErrors(oldModel[prop]);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}
catch (e) {
console.warn(sf("Model should be validatable but its not"));
}
}
}
if (err) {
result = result || {};
result[prop] = err;
}
}
}
return result ? new ModelErrorDefinition(result) : undefined;
}
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9tb2RlbC92YWxpZGF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCxvQkFBb0IsRUFFcEIsU0FBUyxFQUNULGNBQWMsRUFDZCxFQUFFLEVBRUYsVUFBVSxFQUNWLGNBQWMsR0FFZixNQUFNLGdDQUFnQyxDQUFDO0FBQ3hDLE9BQU8sRUFBcUIsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDckUsT0FBTyxFQUFFLG9CQUFvQixFQUFtQixNQUFNLGVBQWUsQ0FBQztBQUN0RSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRTFDOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FDN0IsUUFBVyxFQUNYLFFBQVcsRUFDWCxHQUFHLFVBQW9CO0lBRXZCLE1BQU0sbUJBQW1CLEdBQTRDLEVBQUUsQ0FBQztJQUN4RSxLQUFLLE1BQU0sSUFBSSxJQUFJLFFBQVE7UUFDekIsSUFDRSxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQztZQUNwRCxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUUvQixtQkFBbUIsQ0FBQyxJQUFJLENBQ3RCLFVBQVUsQ0FBQyxxQkFBcUIsQ0FDOUIsb0JBQW9CLENBQUMsT0FBTyxFQUM1QixRQUFRLEVBQ1IsSUFBSSxDQUNvQyxDQUMzQyxDQUFDO0lBRU4sSUFBSSxNQUFNLEdBQTRCLFNBQVMsQ0FBQztJQUVoRCxLQUFLLE1BQU0saUJBQWlCLElBQUksbUJBQW1CLEVBQUUsQ0FBQztRQUNwRCxNQUFNLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxHQUFHLGlCQUFpQixDQUFDO1FBRS9DLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLDJFQUEyRTtRQUUvRixJQUFJLENBQUMsVUFBVSxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU07WUFBRSxTQUFTO1FB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Q0FBQztnQkFDdEIsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQVUsQ0FBQztZQUM1QixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQy9ELENBQUMiLCJmaWxlIjoibW9kZWwvdmFsaWRhdGlvbi5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIE1vZGVsLFxuICBNb2RlbEVycm9yRGVmaW5pdGlvbixcbiAgTW9kZWxFcnJvcnMsXG4gIE1vZGVsS2V5cyxcbiAgUmVzZXJ2ZWRNb2RlbHMsXG4gIHNmLFxuICBWYWxpZGF0YWJsZSxcbiAgVmFsaWRhdGlvbixcbiAgVmFsaWRhdGlvbktleXMsXG4gIFZhbGlkYXRpb25Qcm9wZXJ0eURlY29yYXRvckRlZmluaXRpb24sXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERlY29yYXRvck1ldGFkYXRhLCBSZWZsZWN0aW9uIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBVcGRhdGVWYWxpZGF0aW9uS2V5cywgVXBkYXRlVmFsaWRhdG9yIH0gZnJvbSBcIi4uL3ZhbGlkYXRpb25cIjtcbmltcG9ydCB7IGZpbmRNb2RlbElkIH0gZnJvbSBcIi4uL2lkZW50aXR5XCI7XG5cbi8qKlxuICogQHN1bW1hcnkgVmFsaWRhdGVzIHRoZSB1cGRhdGUgb2YgYSBtb2RlbFxuICpcbiAqIEBwYXJhbSB7VH0gb2xkTW9kZWxcbiAqIEBwYXJhbSB7VH0gbmV3TW9kZWxcbiAqIEBwYXJhbSB7c3RyaW5nW119IFtleGNlcHRpb25zXVxuICpcbiAqIEBmdW5jdGlvbiB2YWxpZGF0ZUNvbXBhcmVcbiAqIEByZXR1cm4ge01vZGVsRXJyb3JEZWZpbml0aW9uIHwgdW5kZWZpbmVkfVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9ycy5Nb2RlbFxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVDb21wYXJlPFQgZXh0ZW5kcyBNb2RlbD4oXG4gIG9sZE1vZGVsOiBULFxuICBuZXdNb2RlbDogVCxcbiAgLi4uZXhjZXB0aW9uczogc3RyaW5nW11cbik6IE1vZGVsRXJyb3JEZWZpbml0aW9uIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgZGVjb3JhdGVkUHJvcGVydGllczogVmFsaWRhdGlvblByb3BlcnR5RGVjb3JhdG9yRGVmaW5pdGlvbltdID0gW107XG4gIGZvciAoY29uc3QgcHJvcCBpbiBuZXdNb2RlbClcbiAgICBpZiAoXG4gICAgICBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobmV3TW9kZWwsIHByb3ApICYmXG4gICAgICBleGNlcHRpb25zLmluZGV4T2YocHJvcCkgPT09IC0xXG4gICAgKVxuICAgICAgZGVjb3JhdGVkUHJvcGVydGllcy5wdXNoKFxuICAgICAgICBSZWZsZWN0aW9uLmdldFByb3BlcnR5RGVjb3JhdG9ycyhcbiAgICAgICAgICBVcGRhdGVWYWxpZGF0aW9uS2V5cy5SRUZMRUNULFxuICAgICAgICAgIG5ld01vZGVsLFxuICAgICAgICAgIHByb3BcbiAgICAgICAgKSBhcyBWYWxpZGF0aW9uUHJvcGVydHlEZWNvcmF0b3JEZWZpbml0aW9uXG4gICAgICApO1xuXG4gIGxldCByZXN1bHQ6IE1vZGVsRXJyb3JzIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gIGZvciAoY29uc3QgZGVjb3JhdGVkUHJvcGVydHkgb2YgZGVjb3JhdGVkUHJvcGVydGllcykge1xuICAgIGNvbnN0IHsgcHJvcCwgZGVjb3JhdG9ycyB9ID0gZGVjb3JhdGVkUHJvcGVydHk7XG5cbiAgICBkZWNvcmF0b3JzLnNoaWZ0KCk7IC8vIHJlbW92ZSB0aGUgZGVzaWduOnR5cGUgZGVjb3JhdG9yLCBzaW5jZSB0aGUgdHlwZSB3aWxsIGFscmVhZHkgYmUgY2hlY2tlZFxuXG4gICAgaWYgKCFkZWNvcmF0b3JzIHx8ICFkZWNvcmF0b3JzLmxlbmd0aCkgY29udGludWU7XG4gICAgbGV0IGVycnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD4gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbiAgICBmb3IgKGNvbnN0IGRlY29yYXRvciBvZiBkZWNvcmF0b3JzKSB7XG4gICAgICBjb25zdCB2YWxpZGF0b3I6IFVwZGF0ZVZhbGlkYXRvciA9IFZhbGlkYXRpb24uZ2V0KFxuICAgICAgICBkZWNvcmF0b3Iua2V5XG4gICAgICApIGFzIFVwZGF0ZVZhbGlkYXRvcjtcbiAgICAgIGlmICghdmFsaWRhdG9yKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgYENvdWxkIG5vdCBmaW5kIE1hdGNoaW5nIHZhbGlkYXRvciBmb3IgJHtkZWNvcmF0b3Iua2V5fSBmb3IgcHJvcGVydHkgJHtTdHJpbmcoZGVjb3JhdGVkUHJvcGVydHkucHJvcCl9YFxuICAgICAgICApO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyOiBzdHJpbmcgfCB1bmRlZmluZWQgPSB2YWxpZGF0b3IudXBkYXRlSGFzRXJyb3JzKFxuICAgICAgICAobmV3TW9kZWwgYXMgYW55KVtwcm9wLnRvU3RyaW5nKCldLFxuICAgICAgICAob2xkTW9kZWwgYXMgYW55KVtwcm9wLnRvU3RyaW5nKCldLFxuICAgICAgICAuLi5PYmplY3QudmFsdWVzKGRlY29yYXRvci5wcm9wcylcbiAgICAgICk7XG5cbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgZXJycyA9IGVycnMgfHwge307XG4gICAgICAgIGVycnNbZGVjb3JhdG9yLmtleV0gPSBlcnI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVycnMpIHtcbiAgICAgIHJlc3VsdCA9IHJlc3VsdCB8fCB7fTtcbiAgICAgIHJlc3VsdFtkZWNvcmF0ZWRQcm9wZXJ0eS5wcm9wLnRvU3RyaW5nKCldID0gZXJycztcbiAgICB9XG4gIH1cbiAgLy8gdGVzdHMgbmVzdGVkIGNsYXNzZXNcbiAgZm9yIChjb25zdCBwcm9wIG9mIE9iamVjdC5rZXlzKG5ld01vZGVsKS5maWx0ZXIoKGspID0+IHtcbiAgICBpZiAoZXhjZXB0aW9ucy5pbmNsdWRlcyhrKSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiAhcmVzdWx0IHx8ICFyZXN1bHRba107XG4gIH0pKSB7XG4gICAgbGV0IGVycjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIC8vIGlmIGEgbmVzdGVkIE1vZGVsXG4gICAgY29uc3QgYWxsRGVjb3JhdG9ycyA9IFJlZmxlY3Rpb24uZ2V0UHJvcGVydHlEZWNvcmF0b3JzKFxuICAgICAgVmFsaWRhdGlvbktleXMuUkVGTEVDVCxcbiAgICAgIG5ld01vZGVsLFxuICAgICAgcHJvcFxuICAgICkuZGVjb3JhdG9ycztcbiAgICBjb25zdCBkZWNvcmF0b3JzID0gUmVmbGVjdGlvbi5nZXRQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICBWYWxpZGF0aW9uS2V5cy5SRUZMRUNULFxuICAgICAgbmV3TW9kZWwsXG4gICAgICBwcm9wXG4gICAgKS5kZWNvcmF0b3JzLmZpbHRlcihcbiAgICAgIChkKSA9PiBbTW9kZWxLZXlzLlRZUEUsIFZhbGlkYXRpb25LZXlzLlRZUEVdLmluZGV4T2YoZC5rZXkpICE9PSAtMVxuICAgICk7XG4gICAgaWYgKCFkZWNvcmF0b3JzIHx8ICFkZWNvcmF0b3JzLmxlbmd0aCkgY29udGludWU7XG4gICAgY29uc3QgZGVjID0gZGVjb3JhdG9ycy5wb3AoKSBhcyBEZWNvcmF0b3JNZXRhZGF0YTtcbiAgICBjb25zdCBjbGF6eiA9IGRlYy5wcm9wcy5uYW1lXG4gICAgICA/IFtkZWMucHJvcHMubmFtZV1cbiAgICAgIDogQXJyYXkuaXNBcnJheShkZWMucHJvcHMuY3VzdG9tVHlwZXMpXG4gICAgICAgID8gZGVjLnByb3BzLmN1c3RvbVR5cGVzXG4gICAgICAgIDogW2RlYy5wcm9wcy5jdXN0b21UeXBlc107XG4gICAgY29uc3QgcmVzZXJ2ZWQgPSBPYmplY3QudmFsdWVzKFJlc2VydmVkTW9kZWxzKS5tYXAoKHYpID0+XG4gICAgICB2LnRvTG93ZXJDYXNlKClcbiAgICApIGFzIHN0cmluZ1tdO1xuXG4gICAgZm9yIChjb25zdCBjIG9mIGNsYXp6KSB7XG4gICAgICBpZiAocmVzZXJ2ZWQuaW5kZXhPZihjLnRvTG93ZXJDYXNlKCkpID09PSAtMSkge1xuICAgICAgICBzd2l0Y2ggKGMpIHtcbiAgICAgICAgICBjYXNlIEFycmF5Lm5hbWU6XG4gICAgICAgICAgY2FzZSBTZXQubmFtZTpcbiAgICAgICAgICAgIGlmIChhbGxEZWNvcmF0b3JzLmxlbmd0aCkge1xuICAgICAgICAgICAgICBjb25zdCBsaXN0RGVjID0gYWxsRGVjb3JhdG9ycy5maW5kKFxuICAgICAgICAgICAgICAgIChkKSA9PiBkLmtleSA9PT0gVmFsaWRhdGlvbktleXMuTElTVFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBpZiAobGlzdERlYykge1xuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50TGlzdCwgb2xkTGlzdDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAoYykge1xuICAgICAgICAgICAgICAgICAgY2FzZSBBcnJheS5uYW1lOlxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50TGlzdCA9IChuZXdNb2RlbCBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtwcm9wXTtcbiAgICAgICAgICAgICAgICAgICAgb2xkTGlzdCA9IChvbGRNb2RlbCBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtwcm9wXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICBjYXNlIFNldC5uYW1lOlxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50TGlzdCA9IChuZXdNb2RlbCBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtcbiAgICAgICAgICAgICAgICAgICAgICBwcm9wXG4gICAgICAgICAgICAgICAgICAgIF0udmFsdWVzKCk7XG4gICAgICAgICAgICAgICAgICAgIG9sZExpc3QgPSAob2xkTW9kZWwgYXMgUmVjb3JkPHN0cmluZywgYW55PilbcHJvcF0udmFsdWVzKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGF0dHJpYnV0ZSB0eXBlICR7Y31gKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBlcnIgPSBjdXJyZW50TGlzdFxuICAgICAgICAgICAgICAgICAgLm1hcCgodjogVmFsaWRhdGFibGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaWQgPSBmaW5kTW9kZWxJZCh2IGFzIGFueSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaWQpIHJldHVybiBcIkZhaWxlZCB0byBmaW5kIG1vZGVsIGlkXCI7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG9sZE1vZGVsID0gb2xkTGlzdC5maW5kKFxuICAgICAgICAgICAgICAgICAgICAgIChlbDogYW55KSA9PiBpZCA9PT0gZmluZE1vZGVsSWQoZWwsIHRydWUpXG4gICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFvbGRNb2RlbCkgcmV0dXJuOyAvLyBub3RoaW5nIHRvIGNvbXBhcmUgd2l0aFxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdi5oYXNFcnJvcnMob2xkTW9kZWwpO1xuICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgIC5maWx0ZXIoKGU6IGFueSkgPT4gISFlKSBhcyBhbnk7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWVycj8ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVzdWx0IGlzIGFuIGVtcHR5IGxpc3QuLi5cbiAgICAgICAgICAgICAgICAgIGVyciA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgKG5ld01vZGVsIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW3Byb3BdICYmXG4gICAgICAgICAgICAgICAgKG9sZE1vZGVsIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW3Byb3BdXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICBlcnIgPSAobmV3TW9kZWwgYXMgUmVjb3JkPHN0cmluZywgYW55PilbcHJvcF0uaGFzRXJyb3JzKFxuICAgICAgICAgICAgICAgICAgKG9sZE1vZGVsIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW3Byb3BdXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgICAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybihzZihcIk1vZGVsIHNob3VsZCBiZSB2YWxpZGF0YWJsZSBidXQgaXRzIG5vdFwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgcmVzdWx0ID0gcmVzdWx0IHx8IHt9O1xuICAgICAgICByZXN1bHRbcHJvcF0gPSBlcnIgYXMgYW55O1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0ID8gbmV3IE1vZGVsRXJyb3JEZWZpbml0aW9uKHJlc3VsdCkgOiB1bmRlZmluZWQ7XG59XG4iXX0=