ness
Version:
✪ No-effort static sites deployed to your AWS account.
308 lines • 48.6 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Deploy = void 0;
const dns = __importStar(require("dns"));
const react_1 = __importStar(require("react"));
const ink_1 = require("ink");
const Task_1 = require("./Task");
const context_1 = require("../context");
const aws_1 = require("../providers/aws");
const utils_1 = require("../utils");
const events = __importStar(require("../utils/events"));
const csp_1 = require("../utils/csp");
const next_1 = require("../utils/next");
const Deploy = () => {
const context = (0, react_1.useContext)(context_1.NessContext);
const [domainDeployed, setDomainDeployed] = (0, react_1.useState)(false);
const [webDeployed, setWebDeployed] = (0, react_1.useState)(false);
const [webAssetsPushed, setWebAssetsPushed] = (0, react_1.useState)(false);
const [aliasDeployed, setAliasDeployed] = (0, react_1.useState)(false);
const [webRedeployed, setWebRedeployed] = (0, react_1.useState)(false);
const [error, setError] = (0, react_1.useState)();
const [siteUrl, setSiteUrl] = (0, react_1.useState)();
const [nameservers, setNameservers] = (0, react_1.useState)();
const [domainOutputs, setDomainOutputs] = (0, react_1.useState)();
const [webOutputs, setWebOutputs] = (0, react_1.useState)();
const [needsRedeploy, setNeedsRedeploy] = (0, react_1.useState)(true);
const [dnsValidated, setDnsValidated] = (0, react_1.useState)(false);
const [nextBuild, setNextBuild] = (0, react_1.useState)();
const { settings, framework } = context;
const { domain, dir, csp, verbose } = settings || {};
const hasCustomDomain = domain !== undefined;
const isNextJs = framework && framework.name === 'next';
const track = async (event, detail = '') => {
await events.emit({
event,
command: 'deploy',
detail,
domain: domain || '',
options: settings || {},
});
};
const handleError = async (stack, error) => {
const reason = await (0, aws_1.getCloudFormationFailureReason)((0, context_1.getStackId)(stack));
setError(`${error}${reason ? `:\n\n${reason}` : ''}`);
};
const deployDomain = async () => {
try {
const zone = await (0, aws_1.getHostedZone)(domain);
const stack = await (0, aws_1.getStack)('domain', { Name: domain, ExistingHostedZoneId: zone === null || zone === void 0 ? void 0 : zone.id });
const outputs = await (0, aws_1.deployStack)({ stack });
setDomainOutputs(outputs);
}
catch (error) {
if (error instanceof Error) {
track('error', error.message);
}
return Task_1.TaskState.Failure;
}
return Task_1.TaskState.Success;
};
const handleDomainDeployed = async (state) => {
if (state === Task_1.TaskState.Failure) {
await handleError('domain', 'Failed to create your custom domain');
return;
}
setDomainDeployed(true);
};
const deploySupportStack = async () => {
try {
const stack = await (0, aws_1.getStack)('support', {});
const outputs = await (0, aws_1.deployStack)({ stack });
return outputs;
}
catch (error) {
if (error instanceof Error) {
track('error', error.message);
}
return undefined;
}
};
const deployWeb = async () => {
const { BucketName: supportBucket, DefaultCachePolicyArn, ImageCachePolicyArn, StaticCachePolicyArn, ImageOriginRequestPolicyArn, } = (await deploySupportStack()) || {};
const webStackId = await (0, context_1.getStackId)('web');
const certificateArn = domain ? await (0, aws_1.getCertificateArn)(domain) : undefined;
const existingDistribution = domain ? await (0, aws_1.getDistribution)(domain) : undefined;
const needsRedeploy = certificateArn === undefined || existingDistribution !== undefined;
if (needsRedeploy)
setNeedsRedeploy(needsRedeploy);
// For next, we need to build lambdas for @edge deploy
let nextBuildLocal = nextBuild;
if (isNextJs && !nextBuildLocal) {
nextBuildLocal = await (0, next_1.buildNextApp)();
setNextBuild(nextBuildLocal);
await (0, aws_1.syncLocalToS3)({
dir: nextBuildLocal.lambdaBuildDir,
bucket: supportBucket,
prefix: `${webStackId}/`,
prune: true,
verbose: verbose,
});
}
const getLambdaPath = (base) => {
return base ? `${webStackId}/${base}` : undefined;
};
try {
const stack = await (0, aws_1.getStack)('web', {
DomainName: domain,
RedirectSubDomainNameWithDot: (settings === null || settings === void 0 ? void 0 : settings.redirectWww) ? 'www.' : undefined,
DefaultRootObject: isNextJs ? '' : settings === null || settings === void 0 ? void 0 : settings.indexDocument,
DefaultErrorObject: (settings === null || settings === void 0 ? void 0 : settings.spa) ? settings === null || settings === void 0 ? void 0 : settings.indexDocument : settings === null || settings === void 0 ? void 0 : settings.errorDocument,
DefaultErrorResponseCode: (settings === null || settings === void 0 ? void 0 : settings.spa) ? '200' : '404',
ExistingCertificate: certificateArn,
IncludeCloudFrontAlias: existingDistribution || !certificateArn ? 'false' : 'true',
ContentSecurityPolicy: csp && csp !== 'auto' ? csp : await (0, csp_1.generateCsp)(dir),
LambdaBucket: supportBucket,
DefaultCachePolicyArn,
ImageCachePolicyArn,
StaticCachePolicyArn,
ImageOriginRequestPolicyArn,
IsNextJs: String(isNextJs),
NextJsDefaultLambdaKey: isNextJs
? getLambdaPath(nextBuildLocal === null || nextBuildLocal === void 0 ? void 0 : nextBuildLocal.defaultLambdaPath)
: undefined,
NextJsImageLambdaKey: isNextJs ? getLambdaPath(nextBuildLocal === null || nextBuildLocal === void 0 ? void 0 : nextBuildLocal.imageLambdaPath) : undefined,
NextJsApiLambdaKey: isNextJs ? getLambdaPath(nextBuildLocal === null || nextBuildLocal === void 0 ? void 0 : nextBuildLocal.apiLambdaPath) : undefined,
NextJsImagePath: isNextJs ? nextBuildLocal === null || nextBuildLocal === void 0 ? void 0 : nextBuildLocal.imagePath : undefined,
NextJsDataPath: isNextJs ? nextBuildLocal === null || nextBuildLocal === void 0 ? void 0 : nextBuildLocal.dataPath : undefined,
NextJsBasePath: isNextJs ? nextBuildLocal === null || nextBuildLocal === void 0 ? void 0 : nextBuildLocal.basePath : undefined,
NextJsStaticPath: isNextJs ? nextBuildLocal === null || nextBuildLocal === void 0 ? void 0 : nextBuildLocal.staticPath : undefined,
NextJsApiPath: isNextJs ? nextBuildLocal === null || nextBuildLocal === void 0 ? void 0 : nextBuildLocal.apiPath : undefined,
NextJsRegenerationLambdaKey: isNextJs
? getLambdaPath(nextBuildLocal === null || nextBuildLocal === void 0 ? void 0 : nextBuildLocal.regenerationLambdaPath)
: undefined,
});
const outputs = await (0, aws_1.deployStack)({ stack });
setWebOutputs(outputs);
setSiteUrl(outputs.URL);
}
catch (error) {
if (error instanceof Error) {
track('error', error.message);
}
return Task_1.TaskState.Failure;
}
return Task_1.TaskState.Success;
};
const handleWebDeployed = async (state) => {
if (state === Task_1.TaskState.Failure) {
await handleError('web', 'Failed to deploy your site');
return;
}
setWebDeployed(true);
};
const pushWebAssets = async () => {
const bucket = webOutputs.BucketName;
const push = async (options) => (0, aws_1.syncLocalToS3)({ ...options, bucket, verbose: verbose });
try {
if (nextBuild) {
const { assets } = nextBuild;
Object.keys(assets).forEach(async (key) => {
const { path: assetPath, cacheControl, prefix } = assets[key];
await push({ dir: assetPath, cacheControl, prefix });
});
}
else {
await push({ dir: dir, prune: true });
}
if (webOutputs === null || webOutputs === void 0 ? void 0 : webOutputs.DistributionId) {
await (0, aws_1.invalidateDistribution)(webOutputs.DistributionId, (nextBuild === null || nextBuild === void 0 ? void 0 : nextBuild.invalidationPaths) || undefined);
}
}
catch (error) {
if (error instanceof Error) {
track('error', error.message);
}
return Task_1.TaskState.Failure;
}
return Task_1.TaskState.Success;
};
const handleWebAssetsPushed = async (state) => {
if (state === Task_1.TaskState.Failure) {
setError('Failed to push assets to S3');
return;
}
setWebAssetsPushed(true);
};
const handleWebRedeployed = async (state) => {
if (state === Task_1.TaskState.Failure) {
await handleError('web', 'Failed to point custom domain at your site');
return;
}
setWebRedeployed(true);
};
const deployAlias = async () => {
var _a;
try {
const hostedZoneId = domainOutputs === null || domainOutputs === void 0 ? void 0 : domainOutputs.HostedZoneId;
const aRecord = await (0, aws_1.getHostedZoneARecord)(hostedZoneId, domain);
// We have to do this the first time we deploy since we dropped the CDK
if (aRecord && ((_a = aRecord.AliasTarget) === null || _a === void 0 ? void 0 : _a.DNSName) !== `${webOutputs === null || webOutputs === void 0 ? void 0 : webOutputs.DistributionDomainName}.`) {
await (0, aws_1.deleteHostedZoneRecords)(hostedZoneId, [aRecord]);
}
const stack = await (0, aws_1.getStack)('alias', {
DomainStack: domainOutputs === null || domainOutputs === void 0 ? void 0 : domainOutputs.StackName,
WebStack: webOutputs === null || webOutputs === void 0 ? void 0 : webOutputs.StackName,
RedirectSubDomainNameWithDot: (settings === null || settings === void 0 ? void 0 : settings.redirectWww) ? 'www.' : undefined,
});
await (0, aws_1.deployStack)({ stack });
// We need to cleanup the record created by ACM when validating the cert
await (0, aws_1.cleanupHostedZoneRecords)(hostedZoneId);
}
catch (error) {
if (error instanceof Error) {
track('error', error.message);
}
return Task_1.TaskState.Failure;
}
return Task_1.TaskState.Success;
};
const handleAliasDeployed = async (state) => {
if (state === Task_1.TaskState.Failure) {
await handleError('alias', 'Failed to setup SSL for your custom domain');
return;
}
setAliasDeployed(true);
};
const validateDns = async () => {
if (!hasCustomDomain)
return Task_1.TaskState.Skipped;
while (true) {
try {
const records = await dns.promises.resolveTxt(`ness.${domain}`);
if (records.flat().find((r) => r.toLowerCase().includes('ness'))) {
return Task_1.TaskState.Success;
}
}
catch (error) {
if (error instanceof Error) {
track('error', error.message);
}
}
finally {
await (0, utils_1.delay)(1000);
}
if (!nameservers) {
const { hostedZoneId } = domainOutputs || {};
if (!hostedZoneId)
return Task_1.TaskState.Failure;
const nameservers = await (0, aws_1.getHostedZoneNameservers)(hostedZoneId);
setNameservers(nameservers);
}
}
};
const onDnsValidated = () => {
setDnsValidated(true);
};
const finished = webDeployed &&
webAssetsPushed &&
(!hasCustomDomain || webRedeployed || (!needsRedeploy && aliasDeployed));
(0, react_1.useEffect)(() => {
track('started');
}, []);
(0, react_1.useEffect)(() => {
if (finished)
track('finished');
}, [finished]);
return (react_1.default.createElement(ink_1.Box, { flexDirection: 'column' },
react_1.default.createElement(Task_1.Task, { name: 'Deploying web infrastructure', note: '\u2615 this could take a while', action: deployWeb, onComplete: handleWebDeployed }),
webDeployed && (react_1.default.createElement(Task_1.Task, { name: `Publishing '${dir}' directory to AWS`, action: pushWebAssets, onComplete: handleWebAssetsPushed })),
hasCustomDomain && (react_1.default.createElement(Task_1.Task, { name: `Setting up custom domain (${domain})`, action: deployDomain, onComplete: handleDomainDeployed, persist: false })),
domainDeployed && (react_1.default.createElement(Task_1.Task, { name: 'Validating custom domain DNS', action: validateDns, persist: false, onComplete: onDnsValidated })),
nameservers && !dnsValidated && (react_1.default.createElement(ink_1.Box, { paddingTop: 1, paddingLeft: 2 },
react_1.default.createElement(ink_1.Text, { color: 'gray' },
"Configure your domain registrar with the following nameservers:",
react_1.default.createElement(ink_1.Newline, null),
react_1.default.createElement(ink_1.Newline, null),
react_1.default.createElement(ink_1.Text, { color: 'cyan' }, nameservers.join('\n'))))),
webDeployed && dnsValidated && (react_1.default.createElement(Task_1.Task, { name: 'Setting up SSL', action: deployAlias, onComplete: handleAliasDeployed, success: 'Finalizing custom domain', persist: !needsRedeploy })),
aliasDeployed && needsRedeploy && (react_1.default.createElement(Task_1.Task, { name: 'Finalizing custom domain', action: deployWeb, onComplete: handleWebRedeployed })),
finished && (react_1.default.createElement(ink_1.Box, { paddingTop: 1 },
react_1.default.createElement(ink_1.Text, null,
react_1.default.createElement(ink_1.Text, null, "\uD83C\uDF89 Site successfully deployed:"),
react_1.default.createElement(ink_1.Newline, null),
react_1.default.createElement(ink_1.Text, null, siteUrl)))),
error && (react_1.default.createElement(ink_1.Box, { paddingTop: 1 },
react_1.default.createElement(ink_1.Text, { color: 'red' }, error)))));
};
exports.Deploy = Deploy;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGVwbG95LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbXBvbmVudHMvRGVwbG95LnRzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEseUNBQTBCO0FBRTFCLCtDQUE0RDtBQUM1RCw2QkFBc0M7QUFFdEMsaUNBQXNDO0FBQ3RDLHdDQUFrRDtBQUNsRCwwQ0FheUI7QUFDekIsb0NBQThCO0FBQzlCLHdEQUF5QztBQUN6QyxzQ0FBd0M7QUFDeEMsd0NBQXFEO0FBRTlDLE1BQU0sTUFBTSxHQUE0QixHQUFHLEVBQUU7SUFDbEQsTUFBTSxPQUFPLEdBQUcsSUFBQSxrQkFBVSxFQUFDLHFCQUFXLENBQUMsQ0FBQTtJQUN2QyxNQUFNLENBQUMsY0FBYyxFQUFFLGlCQUFpQixDQUFDLEdBQUcsSUFBQSxnQkFBUSxFQUFDLEtBQUssQ0FBQyxDQUFBO0lBQzNELE1BQU0sQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLEdBQUcsSUFBQSxnQkFBUSxFQUFDLEtBQUssQ0FBQyxDQUFBO0lBQ3JELE1BQU0sQ0FBQyxlQUFlLEVBQUUsa0JBQWtCLENBQUMsR0FBRyxJQUFBLGdCQUFRLEVBQUMsS0FBSyxDQUFDLENBQUE7SUFDN0QsTUFBTSxDQUFDLGFBQWEsRUFBRSxnQkFBZ0IsQ0FBQyxHQUFHLElBQUEsZ0JBQVEsRUFBQyxLQUFLLENBQUMsQ0FBQTtJQUN6RCxNQUFNLENBQUMsYUFBYSxFQUFFLGdCQUFnQixDQUFDLEdBQUcsSUFBQSxnQkFBUSxFQUFDLEtBQUssQ0FBQyxDQUFBO0lBRXpELE1BQU0sQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLEdBQUcsSUFBQSxnQkFBUSxHQUFVLENBQUE7SUFFNUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsR0FBRyxJQUFBLGdCQUFRLEdBQVUsQ0FBQTtJQUNoRCxNQUFNLENBQUMsV0FBVyxFQUFFLGNBQWMsQ0FBQyxHQUFHLElBQUEsZ0JBQVEsR0FBWSxDQUFBO0lBQzFELE1BQU0sQ0FBQyxhQUFhLEVBQUUsZ0JBQWdCLENBQUMsR0FBRyxJQUFBLGdCQUFRLEdBQTBCLENBQUE7SUFDNUUsTUFBTSxDQUFDLFVBQVUsRUFBRSxhQUFhLENBQUMsR0FBRyxJQUFBLGdCQUFRLEdBQTBCLENBQUE7SUFDdEUsTUFBTSxDQUFDLGFBQWEsRUFBRSxnQkFBZ0IsQ0FBQyxHQUFHLElBQUEsZ0JBQVEsRUFBQyxJQUFJLENBQUMsQ0FBQTtJQUN4RCxNQUFNLENBQUMsWUFBWSxFQUFFLGVBQWUsQ0FBQyxHQUFHLElBQUEsZ0JBQVEsRUFBQyxLQUFLLENBQUMsQ0FBQTtJQUN2RCxNQUFNLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxHQUFHLElBQUEsZ0JBQVEsR0FBYSxDQUFBO0lBQ3ZELE1BQU0sRUFBQyxRQUFRLEVBQUUsU0FBUyxFQUFDLEdBQUcsT0FBTyxDQUFBO0lBQ3JDLE1BQU0sRUFBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUMsR0FBRyxRQUFRLElBQUksRUFBRSxDQUFBO0lBRWxELE1BQU0sZUFBZSxHQUFHLE1BQU0sS0FBSyxTQUFTLENBQUE7SUFDNUMsTUFBTSxRQUFRLEdBQUcsU0FBUyxJQUFJLFNBQVMsQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFBO0lBRXZELE1BQU0sS0FBSyxHQUFHLEtBQUssRUFBRSxLQUFhLEVBQUUsTUFBTSxHQUFHLEVBQUUsRUFBRSxFQUFFO1FBQ2pELE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQztZQUNoQixLQUFLO1lBQ0wsT0FBTyxFQUFFLFFBQVE7WUFDakIsTUFBTTtZQUNOLE1BQU0sRUFBRSxNQUFNLElBQUksRUFBRTtZQUNwQixPQUFPLEVBQUUsUUFBUSxJQUFJLEVBQUU7U0FDeEIsQ0FBQyxDQUFBO0lBQ0osQ0FBQyxDQUFBO0lBRUQsTUFBTSxXQUFXLEdBQUcsS0FBSyxFQUFFLEtBQWEsRUFBRSxLQUFhLEVBQUUsRUFBRTtRQUN6RCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUEsb0NBQThCLEVBQUMsSUFBQSxvQkFBVSxFQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7UUFDdEUsUUFBUSxDQUFDLEdBQUcsS0FBSyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQTtJQUN2RCxDQUFDLENBQUE7SUFFRCxNQUFNLFlBQVksR0FBNkIsS0FBSyxJQUFJLEVBQUU7UUFDeEQsSUFBSTtZQUNGLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBQSxtQkFBYSxFQUFDLE1BQU8sQ0FBQyxDQUFBO1lBQ3pDLE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBQSxjQUFRLEVBQUMsUUFBUSxFQUFFLEVBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxvQkFBb0IsRUFBRSxJQUFJLGFBQUosSUFBSSx1QkFBSixJQUFJLENBQUUsRUFBRSxFQUFDLENBQUMsQ0FBQTtZQUN0RixNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUEsaUJBQVcsRUFBQyxFQUFDLEtBQUssRUFBQyxDQUFDLENBQUE7WUFDMUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUE7U0FDMUI7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLElBQUksS0FBSyxZQUFZLEtBQUssRUFBRTtnQkFDMUIsS0FBSyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7YUFDOUI7WUFDRCxPQUFPLGdCQUFTLENBQUMsT0FBTyxDQUFBO1NBQ3pCO1FBRUQsT0FBTyxnQkFBUyxDQUFDLE9BQU8sQ0FBQTtJQUMxQixDQUFDLENBQUE7SUFFRCxNQUFNLG9CQUFvQixHQUFHLEtBQUssRUFBRSxLQUFnQixFQUFFLEVBQUU7UUFDdEQsSUFBSSxLQUFLLEtBQUssZ0JBQVMsQ0FBQyxPQUFPLEVBQUU7WUFDL0IsTUFBTSxXQUFXLENBQUMsUUFBUSxFQUFFLHFDQUFxQyxDQUFDLENBQUE7WUFDbEUsT0FBTTtTQUNQO1FBRUQsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDekIsQ0FBQyxDQUFBO0lBRUQsTUFBTSxrQkFBa0IsR0FBc0QsS0FBSyxJQUFJLEVBQUU7UUFDdkYsSUFBSTtZQUNGLE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBQSxjQUFRLEVBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFBO1lBQzNDLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBQSxpQkFBVyxFQUFDLEVBQUMsS0FBSyxFQUFDLENBQUMsQ0FBQTtZQUMxQyxPQUFPLE9BQU8sQ0FBQTtTQUNmO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZCxJQUFJLEtBQUssWUFBWSxLQUFLLEVBQUU7Z0JBQzFCLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFBO2FBQzlCO1lBQ0QsT0FBTyxTQUFTLENBQUE7U0FDakI7SUFDSCxDQUFDLENBQUE7SUFFRCxNQUFNLFNBQVMsR0FBNkIsS0FBSyxJQUFJLEVBQUU7UUFDckQsTUFBTSxFQUNKLFVBQVUsRUFBRSxhQUFhLEVBQ3pCLHFCQUFxQixFQUNyQixtQkFBbUIsRUFDbkIsb0JBQW9CLEVBQ3BCLDJCQUEyQixHQUM1QixHQUFHLENBQUMsTUFBTSxrQkFBa0IsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFBO1FBQ3RDLE1BQU0sVUFBVSxHQUFHLE1BQU0sSUFBQSxvQkFBVSxFQUFDLEtBQUssQ0FBQyxDQUFBO1FBRTFDLE1BQU0sY0FBYyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFBLHVCQUFpQixFQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUE7UUFDM0UsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sSUFBQSxxQkFBZSxFQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUE7UUFDL0UsTUFBTSxhQUFhLEdBQUcsY0FBYyxLQUFLLFNBQVMsSUFBSSxvQkFBb0IsS0FBSyxTQUFTLENBQUE7UUFFeEYsSUFBSSxhQUFhO1lBQUUsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLENBQUE7UUFFbEQsc0RBQXNEO1FBQ3RELElBQUksY0FBYyxHQUFHLFNBQVMsQ0FBQTtRQUM5QixJQUFJLFFBQVEsSUFBSSxDQUFDLGNBQWMsRUFBRTtZQUMvQixjQUFjLEdBQUcsTUFBTSxJQUFBLG1CQUFZLEdBQUUsQ0FBQTtZQUNyQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUE7WUFFNUIsTUFBTSxJQUFBLG1CQUFhLEVBQUM7Z0JBQ2xCLEdBQUcsRUFBRSxjQUFjLENBQUMsY0FBYztnQkFDbEMsTUFBTSxFQUFFLGFBQWE7Z0JBQ3JCLE1BQU0sRUFBRSxHQUFHLFVBQVUsR0FBRztnQkFDeEIsS0FBSyxFQUFFLElBQUk7Z0JBQ1gsT0FBTyxFQUFFLE9BQU87YUFDakIsQ0FBQyxDQUFBO1NBQ0g7UUFFRCxNQUFNLGFBQWEsR0FBRyxDQUFDLElBQXdCLEVBQXNCLEVBQUU7WUFDckUsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsVUFBVSxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUE7UUFDbkQsQ0FBQyxDQUFBO1FBRUQsSUFBSTtZQUNGLE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBQSxjQUFRLEVBQUMsS0FBSyxFQUFFO2dCQUNsQyxVQUFVLEVBQUUsTUFBTTtnQkFDbEIsNEJBQTRCLEVBQUUsQ0FBQSxRQUFRLGFBQVIsUUFBUSx1QkFBUixRQUFRLENBQUUsV0FBVyxFQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFNBQVM7Z0JBQ3hFLGlCQUFpQixFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLGFBQVIsUUFBUSx1QkFBUixRQUFRLENBQUUsYUFBYTtnQkFDMUQsa0JBQWtCLEVBQUUsQ0FBQSxRQUFRLGFBQVIsUUFBUSx1QkFBUixRQUFRLENBQUUsR0FBRyxFQUFDLENBQUMsQ0FBQyxRQUFRLGFBQVIsUUFBUSx1QkFBUixRQUFRLENBQUUsYUFBYSxDQUFDLENBQUMsQ0FBQyxRQUFRLGFBQVIsUUFBUSx1QkFBUixRQUFRLENBQUUsYUFBYTtnQkFDckYsd0JBQXdCLEVBQUUsQ0FBQSxRQUFRLGFBQVIsUUFBUSx1QkFBUixRQUFRLENBQUUsR0FBRyxFQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUs7Z0JBQ3ZELG1CQUFtQixFQUFFLGNBQWM7Z0JBQ25DLHNCQUFzQixFQUFFLG9CQUFvQixJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU07Z0JBQ2xGLHFCQUFxQixFQUFFLEdBQUcsSUFBSSxHQUFHLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sSUFBQSxpQkFBVyxFQUFDLEdBQUksQ0FBQztnQkFDNUUsWUFBWSxFQUFFLGFBQWE7Z0JBQzNCLHFCQUFxQjtnQkFDckIsbUJBQW1CO2dCQUNuQixvQkFBb0I7Z0JBQ3BCLDJCQUEyQjtnQkFDM0IsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUM7Z0JBQzFCLHNCQUFzQixFQUFFLFFBQVE7b0JBQzlCLENBQUMsQ0FBQyxhQUFhLENBQUMsY0FBYyxhQUFkLGNBQWMsdUJBQWQsY0FBYyxDQUFFLGlCQUFpQixDQUFDO29CQUNsRCxDQUFDLENBQUMsU0FBUztnQkFDYixvQkFBb0IsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxjQUFjLGFBQWQsY0FBYyx1QkFBZCxjQUFjLENBQUUsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVM7Z0JBQzNGLGtCQUFrQixFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLGNBQWMsYUFBZCxjQUFjLHVCQUFkLGNBQWMsQ0FBRSxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUztnQkFDdkYsZUFBZSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsY0FBYyxhQUFkLGNBQWMsdUJBQWQsY0FBYyxDQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsU0FBUztnQkFDakUsY0FBYyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsY0FBYyxhQUFkLGNBQWMsdUJBQWQsY0FBYyxDQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUztnQkFDL0QsY0FBYyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsY0FBYyxhQUFkLGNBQWMsdUJBQWQsY0FBYyxDQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUztnQkFDL0QsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxjQUFjLGFBQWQsY0FBYyx1QkFBZCxjQUFjLENBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxTQUFTO2dCQUNuRSxhQUFhLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxjQUFjLGFBQWQsY0FBYyx1QkFBZCxjQUFjLENBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTO2dCQUM3RCwyQkFBMkIsRUFBRSxRQUFRO29CQUNuQyxDQUFDLENBQUMsYUFBYSxDQUFDLGNBQWMsYUFBZCxjQUFjLHVCQUFkLGNBQWMsQ0FBRSxzQkFBc0IsQ0FBQztvQkFDdkQsQ0FBQyxDQUFDLFNBQVM7YUFDZCxDQUFDLENBQUE7WUFFRixNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUEsaUJBQVcsRUFBQyxFQUFDLEtBQUssRUFBQyxDQUFDLENBQUE7WUFDMUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFBO1lBQ3RCLFVBQVUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUE7U0FDeEI7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLElBQUksS0FBSyxZQUFZLEtBQUssRUFBRTtnQkFDMUIsS0FBSyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7YUFDOUI7WUFDRCxPQUFPLGdCQUFTLENBQUMsT0FBTyxDQUFBO1NBQ3pCO1FBRUQsT0FBTyxnQkFBUyxDQUFDLE9BQU8sQ0FBQTtJQUMxQixDQUFDLENBQUE7SUFFRCxNQUFNLGlCQUFpQixHQUFHLEtBQUssRUFBRSxLQUFnQixFQUFFLEVBQUU7UUFDbkQsSUFBSSxLQUFLLEtBQUssZ0JBQVMsQ0FBQyxPQUFPLEVBQUU7WUFDL0IsTUFBTSxXQUFXLENBQUMsS0FBSyxFQUFFLDRCQUE0QixDQUFDLENBQUE7WUFDdEQsT0FBTTtTQUNQO1FBRUQsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQ3RCLENBQUMsQ0FBQTtJQUVELE1BQU0sYUFBYSxHQUE2QixLQUFLLElBQUksRUFBRTtRQUN6RCxNQUFNLE1BQU0sR0FBRyxVQUFXLENBQUMsVUFBVSxDQUFBO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFBRSxPQUtuQixFQUFFLEVBQUUsQ0FBQyxJQUFBLG1CQUFhLEVBQUMsRUFBQyxHQUFHLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBQyxDQUFDLENBQUE7UUFFM0QsSUFBSTtZQUNGLElBQUksU0FBUyxFQUFFO2dCQUNiLE1BQU0sRUFBQyxNQUFNLEVBQUMsR0FBRyxTQUFTLENBQUE7Z0JBRTFCLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRTtvQkFDeEMsTUFBTSxFQUFDLElBQUksRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBQyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQTtvQkFDM0QsTUFBTSxJQUFJLENBQUMsRUFBQyxHQUFHLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUMsQ0FBQyxDQUFBO2dCQUNwRCxDQUFDLENBQUMsQ0FBQTthQUNIO2lCQUFNO2dCQUNMLE1BQU0sSUFBSSxDQUFDLEVBQUMsR0FBRyxFQUFFLEdBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQTthQUNyQztZQUVELElBQUksVUFBVSxhQUFWLFVBQVUsdUJBQVYsVUFBVSxDQUFFLGNBQWMsRUFBRTtnQkFDOUIsTUFBTSxJQUFBLDRCQUFzQixFQUMxQixVQUFVLENBQUMsY0FBYyxFQUN6QixDQUFBLFNBQVMsYUFBVCxTQUFTLHVCQUFULFNBQVMsQ0FBRSxpQkFBaUIsS0FBSSxTQUFTLENBQzFDLENBQUE7YUFDRjtTQUNGO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZCxJQUFJLEtBQUssWUFBWSxLQUFLLEVBQUU7Z0JBQzFCLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFBO2FBQzlCO1lBQ0QsT0FBTyxnQkFBUyxDQUFDLE9BQU8sQ0FBQTtTQUN6QjtRQUVELE9BQU8sZ0JBQVMsQ0FBQyxPQUFPLENBQUE7SUFDMUIsQ0FBQyxDQUFBO0lBRUQsTUFBTSxxQkFBcUIsR0FBRyxLQUFLLEVBQUUsS0FBZ0IsRUFBRSxFQUFFO1FBQ3ZELElBQUksS0FBSyxLQUFLLGdCQUFTLENBQUMsT0FBTyxFQUFFO1lBQy9CLFFBQVEsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFBO1lBQ3ZDLE9BQU07U0FDUDtRQUVELGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFBO0lBQzFCLENBQUMsQ0FBQTtJQUVELE1BQU0sbUJBQW1CLEdBQUcsS0FBSyxFQUFFLEtBQWdCLEVBQUUsRUFBRTtRQUNyRCxJQUFJLEtBQUssS0FBSyxnQkFBUyxDQUFDLE9BQU8sRUFBRTtZQUMvQixNQUFNLFdBQVcsQ0FBQyxLQUFLLEVBQUUsNENBQTRDLENBQUMsQ0FBQTtZQUN0RSxPQUFNO1NBQ1A7UUFFRCxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUN4QixDQUFDLENBQUE7SUFFRCxNQUFNLFdBQVcsR0FBNkIsS0FBSyxJQUFJLEVBQUU7O1FBQ3ZELElBQUk7WUFDRixNQUFNLFlBQVksR0FBRyxhQUFhLGFBQWIsYUFBYSx1QkFBYixhQUFhLENBQUUsWUFBYSxDQUFBO1lBQ2pELE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBQSwwQkFBb0IsRUFBQyxZQUFZLEVBQUUsTUFBTSxDQUFDLENBQUE7WUFFaEUsdUVBQXVFO1lBQ3ZFLElBQUksT0FBTyxJQUFJLENBQUEsTUFBQSxPQUFPLENBQUMsV0FBVywwQ0FBRSxPQUFPLE1BQUssR0FBRyxVQUFVLGFBQVYsVUFBVSx1QkFBVixVQUFVLENBQUUsc0JBQXNCLEdBQUcsRUFBRTtnQkFDeEYsTUFBTSxJQUFBLDZCQUF1QixFQUFDLFlBQVksRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUE7YUFDdkQ7WUFFRCxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUEsY0FBUSxFQUFDLE9BQU8sRUFBRTtnQkFDcEMsV0FBVyxFQUFFLGFBQWEsYUFBYixhQUFhLHVCQUFiLGFBQWEsQ0FBRSxTQUFTO2dCQUNyQyxRQUFRLEVBQUUsVUFBVSxhQUFWLFVBQVUsdUJBQVYsVUFBVSxDQUFFLFNBQVM7Z0JBQy9CLDRCQUE0QixFQUFFLENBQUEsUUFBUSxhQUFSLFFBQVEsdUJBQVIsUUFBUSxDQUFFLFdBQVcsRUFBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxTQUFTO2FBQ3pFLENBQUMsQ0FBQTtZQUVGLE1BQU0sSUFBQSxpQkFBVyxFQUFDLEVBQUMsS0FBSyxFQUFDLENBQUMsQ0FBQTtZQUUxQix3RUFBd0U7WUFDeEUsTUFBTSxJQUFBLDhCQUF3QixFQUFDLFlBQVksQ0FBQyxDQUFBO1NBQzdDO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZCxJQUFJLEtBQUssWUFBWSxLQUFLLEVBQUU7Z0JBQzFCLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFBO2FBQzlCO1lBQ0QsT0FBTyxnQkFBUyxDQUFDLE9BQU8sQ0FBQTtTQUN6QjtRQUVELE9BQU8sZ0JBQVMsQ0FBQyxPQUFPLENBQUE7SUFDMUIsQ0FBQyxDQUFBO0lBRUQsTUFBTSxtQkFBbUIsR0FBRyxLQUFLLEVBQUUsS0FBZ0IsRUFBRSxFQUFFO1FBQ3JELElBQUksS0FBSyxLQUFLLGdCQUFTLENBQUMsT0FBTyxFQUFFO1lBQy9CLE1BQU0sV0FBVyxDQUFDLE9BQU8sRUFBRSw0Q0FBNEMsQ0FBQyxDQUFBO1lBQ3hFLE9BQU07U0FDUDtRQUVELGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFBO0lBQ3hCLENBQUMsQ0FBQTtJQUVELE1BQU0sV0FBVyxHQUFHLEtBQUssSUFBd0IsRUFBRTtRQUNqRCxJQUFJLENBQUMsZUFBZTtZQUFFLE9BQU8sZ0JBQVMsQ0FBQyxPQUFPLENBQUE7UUFFOUMsT0FBTyxJQUFJLEVBQUU7WUFDWCxJQUFJO2dCQUNGLE1BQU0sT0FBTyxHQUFHLE1BQU0sR0FBRyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsUUFBUSxNQUFPLEVBQUUsQ0FBQyxDQUFBO2dCQUNoRSxJQUFJLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRTtvQkFDaEUsT0FBTyxnQkFBUyxDQUFDLE9BQU8sQ0FBQTtpQkFDekI7YUFDRjtZQUFDLE9BQU8sS0FBSyxFQUFFO2dCQUNkLElBQUksS0FBSyxZQUFZLEtBQUssRUFBRTtvQkFDMUIsS0FBSyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7aUJBQzlCO2FBQ0Y7b0JBQVM7Z0JBQ1IsTUFBTSxJQUFBLGFBQUssRUFBQyxJQUFJLENBQUMsQ0FBQTthQUNsQjtZQUVELElBQUksQ0FBQyxXQUFXLEVBQUU7Z0JBQ2hCLE1BQU0sRUFBQyxZQUFZLEVBQUMsR0FBRyxhQUFhLElBQUksRUFBRSxDQUFBO2dCQUMxQyxJQUFJLENBQUMsWUFBWTtvQkFBRSxPQUFPLGdCQUFTLENBQUMsT0FBTyxDQUFBO2dCQUUzQyxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUEsOEJBQXdCLEVBQUMsWUFBWSxDQUFDLENBQUE7Z0JBQ2hFLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQTthQUM1QjtTQUNGO0lBQ0gsQ0FBQyxDQUFBO0lBRUQsTUFBTSxjQUFjLEdBQUcsR0FBRyxFQUFFO1FBQzFCLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUN2QixDQUFDLENBQUE7SUFFRCxNQUFNLFFBQVEsR0FDWixXQUFXO1FBQ1gsZUFBZTtRQUNmLENBQUMsQ0FBQyxlQUFlLElBQUksYUFBYSxJQUFJLENBQUMsQ0FBQyxhQUFhLElBQUksYUFBYSxDQUFDLENBQUMsQ0FBQTtJQUUxRSxJQUFBLGlCQUFTLEVBQUMsR0FBRyxFQUFFO1FBQ2IsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFBO0lBQ2xCLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQTtJQUVOLElBQUEsaUJBQVMsRUFBQyxHQUFHLEVBQUU7UUFDYixJQUFJLFFBQVE7WUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDakMsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQTtJQUVkLE9BQU8sQ0FDTCw4QkFBQyxTQUFHLElBQUMsYUFBYSxFQUFDLFFBQVE7UUFDekIsOEJBQUMsV0FBSSxJQUNILElBQUksRUFBQyw4QkFBOEIsRUFDbkMsSUFBSSxFQUFDLGdDQUEyQixFQUNoQyxNQUFNLEVBQUUsU0FBUyxFQUNqQixVQUFVLEVBQUUsaUJBQWlCLEdBQzdCO1FBQ0QsV0FBVyxJQUFJLENBQ2QsOEJBQUMsV0FBSSxJQUNILElBQUksRUFBRSxlQUFlLEdBQUcsb0JBQW9CLEVBQzVDLE1BQU0sRUFBRSxhQUFhLEVBQ3JCLFVBQVUsRUFBRSxxQkFBcUIsR0FDakMsQ0FDSDtRQUNBLGVBQWUsSUFBSSxDQUNsQiw4QkFBQyxXQUFJLElBQ0gsSUFBSSxFQUFFLDZCQUE2QixNQUFNLEdBQUcsRUFDNUMsTUFBTSxFQUFFLFlBQVksRUFDcEIsVUFBVSxFQUFFLG9CQUFvQixFQUNoQyxPQUFPLEVBQUUsS0FBSyxHQUNkLENBQ0g7UUFDQSxjQUFjLElBQUksQ0FDakIsOEJBQUMsV0FBSSxJQUNILElBQUksRUFBQyw4QkFBOEIsRUFDbkMsTUFBTSxFQUFFLFdBQVcsRUFDbkIsT0FBTyxFQUFFLEtBQUssRUFDZCxVQUFVLEVBQUUsY0FBYyxHQUMxQixDQUNIO1FBQ0EsV0FBVyxJQUFJLENBQUMsWUFBWSxJQUFJLENBQy9CLDhCQUFDLFNBQUcsSUFBQyxVQUFVLEVBQUUsQ0FBQyxFQUFFLFdBQVcsRUFBRSxDQUFDO1lBQ2hDLDhCQUFDLFVBQUksSUFBQyxLQUFLLEVBQUMsTUFBTTs7Z0JBRWhCLDhCQUFDLGFBQU8sT0FBRztnQkFDWCw4QkFBQyxhQUFPLE9BQUc7Z0JBQ1gsOEJBQUMsVUFBSSxJQUFDLEtBQUssRUFBQyxNQUFNLElBQUUsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBUSxDQUM3QyxDQUNILENBQ1A7UUFDQSxXQUFXLElBQUksWUFBWSxJQUFJLENBQzlCLDhCQUFDLFdBQUksSUFDSCxJQUFJLEVBQUMsZ0JBQWdCLEVBQ3JCLE1BQU0sRUFBRSxXQUFXLEVBQ25CLFVBQVUsRUFBRSxtQkFBbUIsRUFDL0IsT0FBTyxFQUFDLDBCQUEwQixFQUNsQyxPQUFPLEVBQUUsQ0FBQyxhQUFhLEdBQ3ZCLENBQ0g7UUFDQSxhQUFhLElBQUksYUFBYSxJQUFJLENBQ2pDLDhCQUFDLFdBQUksSUFBQyxJQUFJLEVBQUMsMEJBQTBCLEVBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsbUJBQW1CLEdBQUksQ0FDN0Y7UUFDQSxRQUFRLElBQUksQ0FDWCw4QkFBQyxTQUFHLElBQUMsVUFBVSxFQUFFLENBQUM7WUFDaEIsOEJBQUMsVUFBSTtnQkFDSCw4QkFBQyxVQUFJLG1EQUFzQztnQkFDM0MsOEJBQUMsYUFBTyxPQUFHO2dCQUNYLDhCQUFDLFVBQUksUUFBRSxPQUFPLENBQVEsQ0FDakIsQ0FDSCxDQUNQO1FBQ0EsS0FBSyxJQUFJLENBQ1IsOEJBQUMsU0FBRyxJQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ2hCLDhCQUFDLFVBQUksSUFBQyxLQUFLLEVBQUMsS0FBSyxJQUFFLEtBQUssQ0FBUSxDQUM1QixDQUNQLENBQ0csQ0FDUCxDQUFBO0FBQ0gsQ0FBQyxDQUFBO0FBblhZLFFBQUEsTUFBTSxVQW1YbEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBkbnMgZnJvbSAnZG5zJ1xuXG5pbXBvcnQgUmVhY3QsIHt1c2VTdGF0ZSwgdXNlQ29udGV4dCwgdXNlRWZmZWN0fSBmcm9tICdyZWFjdCdcbmltcG9ydCB7Qm94LCBOZXdsaW5lLCBUZXh0fSBmcm9tICdpbmsnXG5cbmltcG9ydCB7VGFzaywgVGFza1N0YXRlfSBmcm9tICcuL1Rhc2snXG5pbXBvcnQge2dldFN0YWNrSWQsIE5lc3NDb250ZXh0fSBmcm9tICcuLi9jb250ZXh0J1xuaW1wb3J0IHtcbiAgY2xlYW51cEhvc3RlZFpvbmVSZWNvcmRzLFxuICBkZWxldGVIb3N0ZWRab25lUmVjb3JkcyxcbiAgZGVwbG95U3RhY2ssXG4gIGdldENlcnRpZmljYXRlQXJuLFxuICBnZXRDbG91ZEZvcm1hdGlvbkZhaWx1cmVSZWFzb24sXG4gIGdldERpc3RyaWJ1dGlvbixcbiAgZ2V0SG9zdGVkWm9uZSxcbiAgZ2V0SG9zdGVkWm9uZUFSZWNvcmQsXG4gIGdldEhvc3RlZFpvbmVOYW1lc2VydmVycyxcbiAgZ2V0U3RhY2ssXG4gIGludmFsaWRhdGVEaXN0cmlidXRpb24sXG4gIHN5bmNMb2NhbFRvUzMsXG59IGZyb20gJy4uL3Byb3ZpZGVycy9hd3MnXG5pbXBvcnQge2RlbGF5fSBmcm9tICcuLi91dGlscydcbmltcG9ydCAqIGFzIGV2ZW50cyBmcm9tICcuLi91dGlscy9ldmVudHMnXG5pbXBvcnQge2dlbmVyYXRlQ3NwfSBmcm9tICcuLi91dGlscy9jc3AnXG5pbXBvcnQge2J1aWxkTmV4dEFwcCwgTmV4dEJ1aWxkfSBmcm9tICcuLi91dGlscy9uZXh0J1xuXG5leHBvcnQgY29uc3QgRGVwbG95OiBSZWFjdC5GdW5jdGlvbkNvbXBvbmVudCA9ICgpID0+IHtcbiAgY29uc3QgY29udGV4dCA9IHVzZUNvbnRleHQoTmVzc0NvbnRleHQpXG4gIGNvbnN0IFtkb21haW5EZXBsb3llZCwgc2V0RG9tYWluRGVwbG95ZWRdID0gdXNlU3RhdGUoZmFsc2UpXG4gIGNvbnN0IFt3ZWJEZXBsb3llZCwgc2V0V2ViRGVwbG95ZWRdID0gdXNlU3RhdGUoZmFsc2UpXG4gIGNvbnN0IFt3ZWJBc3NldHNQdXNoZWQsIHNldFdlYkFzc2V0c1B1c2hlZF0gPSB1c2VTdGF0ZShmYWxzZSlcbiAgY29uc3QgW2FsaWFzRGVwbG95ZWQsIHNldEFsaWFzRGVwbG95ZWRdID0gdXNlU3RhdGUoZmFsc2UpXG4gIGNvbnN0IFt3ZWJSZWRlcGxveWVkLCBzZXRXZWJSZWRlcGxveWVkXSA9IHVzZVN0YXRlKGZhbHNlKVxuXG4gIGNvbnN0IFtlcnJvciwgc2V0RXJyb3JdID0gdXNlU3RhdGU8c3RyaW5nPigpXG5cbiAgY29uc3QgW3NpdGVVcmwsIHNldFNpdGVVcmxdID0gdXNlU3RhdGU8c3RyaW5nPigpXG4gIGNvbnN0IFtuYW1lc2VydmVycywgc2V0TmFtZXNlcnZlcnNdID0gdXNlU3RhdGU8c3RyaW5nW10+KClcbiAgY29uc3QgW2RvbWFpbk91dHB1dHMsIHNldERvbWFpbk91dHB1dHNdID0gdXNlU3RhdGU8UmVjb3JkPHN0cmluZywgc3RyaW5nPj4oKVxuICBjb25zdCBbd2ViT3V0cHV0cywgc2V0V2ViT3V0cHV0c10gPSB1c2VTdGF0ZTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PigpXG4gIGNvbnN0IFtuZWVkc1JlZGVwbG95LCBzZXROZWVkc1JlZGVwbG95XSA9IHVzZVN0YXRlKHRydWUpXG4gIGNvbnN0IFtkbnNWYWxpZGF0ZWQsIHNldERuc1ZhbGlkYXRlZF0gPSB1c2VTdGF0ZShmYWxzZSlcbiAgY29uc3QgW25leHRCdWlsZCwgc2V0TmV4dEJ1aWxkXSA9IHVzZVN0YXRlPE5leHRCdWlsZD4oKVxuICBjb25zdCB7c2V0dGluZ3MsIGZyYW1ld29ya30gPSBjb250ZXh0XG4gIGNvbnN0IHtkb21haW4sIGRpciwgY3NwLCB2ZXJib3NlfSA9IHNldHRpbmdzIHx8IHt9XG5cbiAgY29uc3QgaGFzQ3VzdG9tRG9tYWluID0gZG9tYWluICE9PSB1bmRlZmluZWRcbiAgY29uc3QgaXNOZXh0SnMgPSBmcmFtZXdvcmsgJiYgZnJhbWV3b3JrLm5hbWUgPT09ICduZXh0J1xuXG4gIGNvbnN0IHRyYWNrID0gYXN5bmMgKGV2ZW50OiBzdHJpbmcsIGRldGFpbCA9ICcnKSA9PiB7XG4gICAgYXdhaXQgZXZlbnRzLmVtaXQoe1xuICAgICAgZXZlbnQsXG4gICAgICBjb21tYW5kOiAnZGVwbG95JyxcbiAgICAgIGRldGFpbCxcbiAgICAgIGRvbWFpbjogZG9tYWluIHx8ICcnLFxuICAgICAgb3B0aW9uczogc2V0dGluZ3MgfHwge30sXG4gICAgfSlcbiAgfVxuXG4gIGNvbnN0IGhhbmRsZUVycm9yID0gYXN5bmMgKHN0YWNrOiBzdHJpbmcsIGVycm9yOiBzdHJpbmcpID0+IHtcbiAgICBjb25zdCByZWFzb24gPSBhd2FpdCBnZXRDbG91ZEZvcm1hdGlvbkZhaWx1cmVSZWFzb24oZ2V0U3RhY2tJZChzdGFjaykpXG4gICAgc2V0RXJyb3IoYCR7ZXJyb3J9JHtyZWFzb24gPyBgOlxcblxcbiR7cmVhc29ufWAgOiAnJ31gKVxuICB9XG5cbiAgY29uc3QgZGVwbG95RG9tYWluOiAoKSA9PiBQcm9taXNlPFRhc2tTdGF0ZT4gPSBhc3luYyAoKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHpvbmUgPSBhd2FpdCBnZXRIb3N0ZWRab25lKGRvbWFpbiEpXG4gICAgICBjb25zdCBzdGFjayA9IGF3YWl0IGdldFN0YWNrKCdkb21haW4nLCB7TmFtZTogZG9tYWluLCBFeGlzdGluZ0hvc3RlZFpvbmVJZDogem9uZT8uaWR9KVxuICAgICAgY29uc3Qgb3V0cHV0cyA9IGF3YWl0IGRlcGxveVN0YWNrKHtzdGFja30pXG4gICAgICBzZXREb21haW5PdXRwdXRzKG91dHB1dHMpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHRyYWNrKCdlcnJvcicsIGVycm9yLm1lc3NhZ2UpXG4gICAgICB9XG4gICAgICByZXR1cm4gVGFza1N0YXRlLkZhaWx1cmVcbiAgICB9XG5cbiAgICByZXR1cm4gVGFza1N0YXRlLlN1Y2Nlc3NcbiAgfVxuXG4gIGNvbnN0IGhhbmRsZURvbWFpbkRlcGxveWVkID0gYXN5bmMgKHN0YXRlOiBUYXNrU3RhdGUpID0+IHtcbiAgICBpZiAoc3RhdGUgPT09IFRhc2tTdGF0ZS5GYWlsdXJlKSB7XG4gICAgICBhd2FpdCBoYW5kbGVFcnJvcignZG9tYWluJywgJ0ZhaWxlZCB0byBjcmVhdGUgeW91ciBjdXN0b20gZG9tYWluJylcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHNldERvbWFpbkRlcGxveWVkKHRydWUpXG4gIH1cblxuICBjb25zdCBkZXBsb3lTdXBwb3J0U3RhY2s6ICgpID0+IFByb21pc2U8UmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IHVuZGVmaW5lZD4gPSBhc3luYyAoKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0YWNrID0gYXdhaXQgZ2V0U3RhY2soJ3N1cHBvcnQnLCB7fSlcbiAgICAgIGNvbnN0IG91dHB1dHMgPSBhd2FpdCBkZXBsb3lTdGFjayh7c3RhY2t9KVxuICAgICAgcmV0dXJuIG91dHB1dHNcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdHJhY2soJ2Vycm9yJywgZXJyb3IubWVzc2FnZSlcbiAgICAgIH1cbiAgICAgIHJldHVybiB1bmRlZmluZWRcbiAgICB9XG4gIH1cblxuICBjb25zdCBkZXBsb3lXZWI6ICgpID0+IFByb21pc2U8VGFza1N0YXRlPiA9IGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB7XG4gICAgICBCdWNrZXROYW1lOiBzdXBwb3J0QnVja2V0LFxuICAgICAgRGVmYXVsdENhY2hlUG9saWN5QXJuLFxuICAgICAgSW1hZ2VDYWNoZVBvbGljeUFybixcbiAgICAgIFN0YXRpY0NhY2hlUG9saWN5QXJuLFxuICAgICAgSW1hZ2VPcmlnaW5SZXF1ZXN0UG9saWN5QXJuLFxuICAgIH0gPSAoYXdhaXQgZGVwbG95U3VwcG9ydFN0YWNrKCkpIHx8IHt9XG4gICAgY29uc3Qgd2ViU3RhY2tJZCA9IGF3YWl0IGdldFN0YWNrSWQoJ3dlYicpXG5cbiAgICBjb25zdCBjZXJ0aWZpY2F0ZUFybiA9IGRvbWFpbiA/IGF3YWl0IGdldENlcnRpZmljYXRlQXJuKGRvbWFpbikgOiB1bmRlZmluZWRcbiAgICBjb25zdCBleGlzdGluZ0Rpc3RyaWJ1dGlvbiA9IGRvbWFpbiA/IGF3YWl0IGdldERpc3RyaWJ1dGlvbihkb21haW4pIDogdW5kZWZpbmVkXG4gICAgY29uc3QgbmVlZHNSZWRlcGxveSA9IGNlcnRpZmljYXRlQXJuID09PSB1bmRlZmluZWQgfHwgZXhpc3RpbmdEaXN0cmlidXRpb24gIT09IHVuZGVmaW5lZFxuXG4gICAgaWYgKG5lZWRzUmVkZXBsb3kpIHNldE5lZWRzUmVkZXBsb3kobmVlZHNSZWRlcGxveSlcblxuICAgIC8vIEZvciBuZXh0LCB3ZSBuZWVkIHRvIGJ1aWxkIGxhbWJkYXMgZm9yIEBlZGdlIGRlcGxveVxuICAgIGxldCBuZXh0QnVpbGRMb2NhbCA9IG5leHRCdWlsZFxuICAgIGlmIChpc05leHRKcyAmJiAhbmV4dEJ1aWxkTG9jYWwpIHtcbiAgICAgIG5leHRCdWlsZExvY2FsID0gYXdhaXQgYnVpbGROZXh0QXBwKClcbiAgICAgIHNldE5leHRCdWlsZChuZXh0QnVpbGRMb2NhbClcblxuICAgICAgYXdhaXQgc3luY0xvY2FsVG9TMyh7XG4gICAgICAgIGRpcjogbmV4dEJ1aWxkTG9jYWwubGFtYmRhQnVpbGREaXIsXG4gICAgICAgIGJ1Y2tldDogc3VwcG9ydEJ1Y2tldCxcbiAgICAgICAgcHJlZml4OiBgJHt3ZWJTdGFja0lkfS9gLFxuICAgICAgICBwcnVuZTogdHJ1ZSxcbiAgICAgICAgdmVyYm9zZTogdmVyYm9zZSxcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgY29uc3QgZ2V0TGFtYmRhUGF0aCA9IChiYXNlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQgPT4ge1xuICAgICAgcmV0dXJuIGJhc2UgPyBgJHt3ZWJTdGFja0lkfS8ke2Jhc2V9YCA6IHVuZGVmaW5lZFxuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBzdGFjayA9IGF3YWl0IGdldFN0YWNrKCd3ZWInLCB7XG4gICAgICAgIERvbWFpbk5hbWU6IGRvbWFpbixcbiAgICAgICAgUmVkaXJlY3RTdWJEb21haW5OYW1lV2l0aERvdDogc2V0dGluZ3M/LnJlZGlyZWN0V3d3ID8gJ3d3dy4nIDogdW5kZWZpbmVkLFxuICAgICAgICBEZWZhdWx0Um9vdE9iamVjdDogaXNOZXh0SnMgPyAnJyA6IHNldHRpbmdzPy5pbmRleERvY3VtZW50LFxuICAgICAgICBEZWZhdWx0RXJyb3JPYmplY3Q6IHNldHRpbmdzPy5zcGEgPyBzZXR0aW5ncz8uaW5kZXhEb2N1bWVudCA6IHNldHRpbmdzPy5lcnJvckRvY3VtZW50LFxuICAgICAgICBEZWZhdWx0RXJyb3JSZXNwb25zZUNvZGU6IHNldHRpbmdzPy5zcGEgPyAnMjAwJyA6ICc0MDQnLFxuICAgICAgICBFeGlzdGluZ0NlcnRpZmljYXRlOiBjZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgSW5jbHVkZUNsb3VkRnJvbnRBbGlhczogZXhpc3RpbmdEaXN0cmlidXRpb24gfHwgIWNlcnRpZmljYXRlQXJuID8gJ2ZhbHNlJyA6ICd0cnVlJyxcbiAgICAgICAgQ29udGVudFNlY3VyaXR5UG9saWN5OiBjc3AgJiYgY3NwICE9PSAnYXV0bycgPyBjc3AgOiBhd2FpdCBnZW5lcmF0ZUNzcChkaXIhKSxcbiAgICAgICAgTGFtYmRhQnVja2V0OiBzdXBwb3J0QnVja2V0LFxuICAgICAgICBEZWZhdWx0Q2FjaGVQb2xpY3lBcm4sXG4gICAgICAgIEltYWdlQ2FjaGVQb2xpY3lBcm4sXG4gICAgICAgIFN0YXRpY0NhY2hlUG9saWN5QXJuLFxuICAgICAgICBJbWFnZU9yaWdpblJlcXVlc3RQb2xpY3lBcm4sXG4gICAgICAgIElzTmV4dEpzOiBTdHJpbmcoaXNOZXh0SnMpLFxuICAgICAgICBOZXh0SnNEZWZhdWx0TGFtYmRhS2V5OiBpc05leHRKc1xuICAgICAgICAgID8gZ2V0TGFtYmRhUGF0aChuZXh0QnVpbGRMb2NhbD8uZGVmYXVsdExhbWJkYVBhdGgpXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgIE5leHRKc0ltYWdlTGFtYmRhS2V5OiBpc05leHRKcyA/IGdldExhbWJkYVBhdGgobmV4dEJ1aWxkTG9jYWw/LmltYWdlTGFtYmRhUGF0aCkgOiB1bmRlZmluZWQsXG4gICAgICAgIE5leHRKc0FwaUxhbWJkYUtleTogaXNOZXh0SnMgPyBnZXRMYW1iZGFQYXRoKG5leHRCdWlsZExvY2FsPy5hcGlMYW1iZGFQYXRoKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgTmV4dEpzSW1hZ2VQYXRoOiBpc05leHRKcyA/IG5leHRCdWlsZExvY2FsPy5pbWFnZVBhdGggOiB1bmRlZmluZWQsXG4gICAgICAgIE5leHRKc0RhdGFQYXRoOiBpc05leHRKcyA/IG5leHRCdWlsZExvY2FsPy5kYXRhUGF0aCA6IHVuZGVmaW5lZCxcbiAgICAgICAgTmV4dEpzQmFzZVBhdGg6IGlzTmV4dEpzID8gbmV4dEJ1aWxkTG9jYWw/LmJhc2VQYXRoIDogdW5kZWZpbmVkLFxuICAgICAgICBOZXh0SnNTdGF0aWNQYXRoOiBpc05leHRKcyA/IG5leHRCdWlsZExvY2FsPy5zdGF0aWNQYXRoIDogdW5kZWZpbmVkLFxuICAgICAgICBOZXh0SnNBcGlQYXRoOiBpc05leHRKcyA/IG5leHRCdWlsZExvY2FsPy5hcGlQYXRoIDogdW5kZWZpbmVkLFxuICAgICAgICBOZXh0SnNSZWdlbmVyYXRpb25MYW1iZGFLZXk6IGlzTmV4dEpzXG4gICAgICAgICAgPyBnZXRMYW1iZGFQYXRoKG5leHRCdWlsZExvY2FsPy5yZWdlbmVyYXRpb25MYW1iZGFQYXRoKVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgfSlcblxuICAgICAgY29uc3Qgb3V0cHV0cyA9IGF3YWl0IGRlcGxveVN0YWNrKHtzdGFja30pXG4gICAgICBzZXRXZWJPdXRwdXRzKG91dHB1dHMpXG4gICAgICBzZXRTaXRlVXJsKG91dHB1dHMuVVJMKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0cmFjaygnZXJyb3InLCBlcnJvci5tZXNzYWdlKVxuICAgICAgfVxuICAgICAgcmV0dXJuIFRhc2tTdGF0ZS5GYWlsdXJlXG4gICAgfVxuXG4gICAgcmV0dXJuIFRhc2tTdGF0ZS5TdWNjZXNzXG4gIH1cblxuICBjb25zdCBoYW5kbGVXZWJEZXBsb3llZCA9IGFzeW5jIChzdGF0ZTogVGFza1N0YXRlKSA9PiB7XG4gICAgaWYgKHN0YXRlID09PSBUYXNrU3RhdGUuRmFpbHVyZSkge1xuICAgICAgYXdhaXQgaGFuZGxlRXJyb3IoJ3dlYicsICdGYWlsZWQgdG8gZGVwbG95IHlvdXIgc2l0ZScpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBzZXRXZWJEZXBsb3llZCh0cnVlKVxuICB9XG5cbiAgY29uc3QgcHVzaFdlYkFzc2V0czogKCkgPT4gUHJvbWlzZTxUYXNrU3RhdGU+ID0gYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGJ1Y2tldCA9IHdlYk91dHB1dHMhLkJ1Y2tldE5hbWVcbiAgICBjb25zdCBwdXNoID0gYXN5bmMgKG9wdGlvbnM6IHtcbiAgICAgIGRpcjogc3RyaW5nXG4gICAgICBwcnVuZT86IGJvb2xlYW5cbiAgICAgIGNhY2hlQ29udHJvbD86IHN0cmluZ1xuICAgICAgcHJlZml4Pzogc3RyaW5nXG4gICAgfSkgPT4gc3luY0xvY2FsVG9TMyh7Li4ub3B0aW9ucywgYnVja2V0LCB2ZXJib3NlOiB2ZXJib3NlfSlcblxuICAgIHRyeSB7XG4gICAgICBpZiAobmV4dEJ1aWxkKSB7XG4gICAgICAgIGNvbnN0IHthc3NldHN9ID0gbmV4dEJ1aWxkXG5cbiAgICAgICAgT2JqZWN0LmtleXMoYXNzZXRzKS5mb3JFYWNoKGFzeW5jIChrZXkpID0+IHtcbiAgICAgICAgICBjb25zdCB7cGF0aDogYXNzZXRQYXRoLCBjYWNoZUNvbnRyb2wsIHByZWZpeH0gPSBhc3NldHNba2V5XVxuICAgICAgICAgIGF3YWl0IHB1c2goe2RpcjogYXNzZXRQYXRoLCBjYWNoZUNvbnRyb2wsIHByZWZpeH0pXG4gICAgICAgIH0pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCBwdXNoKHtkaXI6IGRpciEsIHBydW5lOiB0cnVlfSlcbiAgICAgIH1cblxuICAgICAgaWYgKHdlYk91dHB1dHM/LkRpc3RyaWJ1dGlvbklkKSB7XG4gICAgICAgIGF3YWl0IGludmFsaWRhdGVEaXN0cmlidXRpb24oXG4gICAgICAgICAgd2ViT3V0cHV0cy5EaXN0cmlidXRpb25JZCxcbiAgICAgICAgICBuZXh0QnVpbGQ/LmludmFsaWRhdGlvblBhdGhzIHx8IHVuZGVmaW5lZCxcbiAgICAgICAgKVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0cmFjaygnZXJyb3InLCBlcnJvci5tZXNzYWdlKVxuICAgICAgfVxuICAgICAgcmV0dXJuIFRhc2tTdGF0ZS5GYWlsdXJlXG4gICAgfVxuXG4gICAgcmV0dXJuIFRhc2tTdGF0ZS5TdWNjZXNzXG4gIH1cblxuICBjb25zdCBoYW5kbGVXZWJBc3NldHNQdXNoZWQgPSBhc3luYyAoc3RhdGU6IFRhc2tTdGF0ZSkgPT4ge1xuICAgIGlmIChzdGF0ZSA9PT0gVGFza1N0YXRlLkZhaWx1cmUpIHtcbiAgICAgIHNldEVycm9yKCdGYWlsZWQgdG8gcHVzaCBhc3NldHMgdG8gUzMnKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgc2V0V2ViQXNzZXRzUHVzaGVkKHRydWUpXG4gIH1cblxuICBjb25zdCBoYW5kbGVXZWJSZWRlcGxveWVkID0gYXN5bmMgKHN0YXRlOiBUYXNrU3RhdGUpID0+IHtcbiAgICBpZiAoc3RhdGUgPT09IFRhc2tTdGF0ZS5GYWlsdXJlKSB7XG4gICAgICBhd2FpdCBoYW5kbGVFcnJvcignd2ViJywgJ0ZhaWxlZCB0byBwb2ludCBjdXN0b20gZG9tYWluIGF0IHlvdXIgc2l0ZScpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBzZXRXZWJSZWRlcGxveWVkKHRydWUpXG4gIH1cblxuICBjb25zdCBkZXBsb3lBbGlhczogKCkgPT4gUHJvbWlzZTxUYXNrU3RhdGU+ID0gYXN5bmMgKCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBob3N0ZWRab25lSWQgPSBkb21haW5PdXRwdXRzPy5Ib3N0ZWRab25lSWQhXG4gICAgICBjb25zdCBhUmVjb3JkID0gYXdhaXQgZ2V0SG9zdGVkWm9uZUFSZWNvcmQoaG9zdGVkWm9uZUlkLCBkb21haW4pXG5cbiAgICAgIC8vIFdlIGhhdmUgdG8gZG8gdGhpcyB0aGUgZmlyc3QgdGltZSB3ZSBkZXBsb3kgc2luY2Ugd2UgZHJvcHBlZCB0aGUgQ0RLXG4gICAgICBpZiAoYVJlY29yZCAmJiBhUmVjb3JkLkFsaWFzVGFyZ2V0Py5ETlNOYW1lICE9PSBgJHt3ZWJPdXRwdXRzPy5EaXN0cmlidXRpb25Eb21haW5OYW1lfS5gKSB7XG4gICAgICAgIGF3YWl0IGRlbGV0ZUhvc3RlZFpvbmVSZWNvcmRzKGhvc3RlZFpvbmVJZCwgW2FSZWNvcmRdKVxuICAgICAgfVxuXG4gICAgICBjb25zdCBzdGFjayA9IGF3YWl0IGdldFN0YWNrKCdhbGlhcycsIHtcbiAgICAgICAgRG9tYWluU3RhY2s6IGRvbWFpbk91dHB1dHM/LlN0YWNrTmFtZSxcbiAgICAgICAgV2ViU3RhY2s6IHdlYk91dHB1dHM/LlN0YWNrTmFtZSxcbiAgICAgICAgUmVkaXJlY3RTdWJEb21haW5OYW1lV2l0aERvdDogc2V0dGluZ3M/LnJlZGlyZWN0V3d3ID8gJ3d3dy4nIDogdW5kZWZpbmVkLFxuICAgICAgfSlcblxuICAgICAgYXdhaXQgZGVwbG95U3RhY2soe3N0YWNrfSlcblxuICAgICAgLy8gV2UgbmVlZCB0byBjbGVhbnVwIHRoZSByZWNvcmQgY3JlYXRlZCBieSBBQ00gd2hlbiB2YWxpZGF0aW5nIHRoZSBjZXJ0XG4gICAgICBhd2FpdCBjbGVhbnVwSG9zdGVkWm9uZVJlY29yZHMoaG9zdGVkWm9uZUlkKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0cmFjaygnZXJyb3InLCBlcnJvci5tZXNzYWdlKVxuICAgICAgfVxuICAgICAgcmV0dXJuIFRhc2tTdGF0ZS5GYWlsdXJlXG4gICAgfVxuXG4gICAgcmV0dXJuIFRhc2tTdGF0ZS5TdWNjZXNzXG4gIH1cblxuICBjb25zdCBoYW5kbGVBbGlhc0RlcGxveWVkID0gYXN5bmMgKHN0YXRlOiBUYXNrU3RhdGUpID0+IHtcbiAgICBpZiAoc3RhdGUgPT09IFRhc2tTdGF0ZS5GYWlsdXJlKSB7XG4gICAgICBhd2FpdCBoYW5kbGVFcnJvcignYWxpYXMnLCAnRmFpbGVkIHRvIHNldHVwIFNTTCBmb3IgeW91ciBjdXN0b20gZG9tYWluJylcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHNldEFsaWFzRGVwbG95ZWQodHJ1ZSlcbiAgfVxuXG4gIGNvbnN0IHZhbGlkYXRlRG5zID0gYXN5bmMgKCk6IFByb21pc2U8VGFza1N0YXRlPiA9PiB7XG4gICAgaWYgKCFoYXNDdXN0b21Eb21haW4pIHJldHVybiBUYXNrU3RhdGUuU2tpcHBlZFxuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlY29yZHMgPSBhd2FpdCBkbnMucHJvbWlzZXMucmVzb2x2ZVR4dChgbmVzcy4ke2RvbWFpbiF9YClcbiAgICAgICAgaWYgKHJlY29yZHMuZmxhdCgpLmZpbmQoKHIpID0+IHIudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygnbmVzcycpKSkge1xuICAgICAgICAgIHJldHVybiBUYXNrU3RhdGUuU3VjY2Vzc1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHRyYWNrKCdlcnJvcicsIGVycm9yLm1lc3NhZ2UpXG4gICAgICAgIH1cbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGF3YWl0IGRlbGF5KDEwMDApXG4gICAgICB9XG5cbiAgICAgIGlmICghbmFtZXNlcnZlcnMpIHtcbiAgICAgICAgY29uc3Qge2hvc3RlZFpvbmVJZH0gPSBkb21haW5PdXRwdXRzIHx8IHt9XG4gICAgICAgIGlmICghaG9zdGVkWm9uZUlkKSByZXR1cm4gVGFza1N0YXRlLkZhaWx1cmVcblxuICAgICAgICBjb25zdCBuYW1lc2VydmVycyA9IGF3YWl0IGdldEhvc3RlZFpvbmVOYW1lc2VydmVycyhob3N0ZWRab25lSWQpXG4gICAgICAgIHNldE5hbWVzZXJ2ZXJzKG5hbWVzZXJ2ZXJzKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IG9uRG5zVmFsaWRhdGVkID0gKCkgPT4ge1xuICAgIHNldERuc1ZhbGlkYXRlZCh0cnVlKVxuICB9XG5cbiAgY29uc3QgZmluaXNoZWQgPVxuICAgIHdlYkRlcGxveWVkICYmXG4gICAgd2ViQXNzZXRzUHVzaGVkICYmXG4gICAgKCFoYXNDdXN0b21Eb21haW4gfHwgd2ViUmVkZXBsb3llZCB8fCAoIW5lZWRzUmVkZXBsb3kgJiYgYWxpYXNEZXBsb3llZCkpXG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICB0cmFjaygnc3RhcnRlZCcpXG4gIH0sIFtdKVxuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKGZpbmlzaGVkKSB0cmFjaygnZmluaXNoZWQnKVxuICB9LCBbZmluaXNoZWRdKVxuXG4gIHJldHVybiAoXG4gICAgPEJveCBmbGV4RGlyZWN0aW9uPSdjb2x1bW4nPlxuICAgICAgPFRhc2tcbiAgICAgICAgbmFtZT0nRGVwbG95aW5nIHdlYiBpbmZyYXN0cnVjdHVyZSdcbiAgICAgICAgbm90ZT0n4piVIHRoaXMgY291bGQgdGFrZSBhIHdoaWxlJ1xuICAgICAgICBhY3Rpb249e2RlcGxveVdlYn1cbiAgICAgICAgb25Db21wbGV0ZT17aGFuZGxlV2ViRGVwbG95ZWR9XG4gICAgICAvPlxuICAgICAge3dlYkRlcGxveWVkICYmIChcbiAgICAgICAgPFRhc2tcbiAgICAgICAgICBuYW1lPXtgUHVibGlzaGluZyAnJHtkaXJ9JyBkaXJlY3RvcnkgdG8gQVdTYH1cbiAgICAgICAgICBhY3Rpb249e3B1c2hXZWJBc3NldHN9XG4gICAgICAgICAgb25Db21wbGV0ZT17aGFuZGxlV2ViQXNzZXRzUHVzaGVkfVxuICAgICAgICAvPlxuICAgICAgKX1cbiAgICAgIHtoYXNDdXN0b21Eb21haW4gJiYgKFxuICAgICAgICA8VGFza1xuICAgICAgICAgIG5hbWU9e2BTZXR0aW5nIHVwIGN1c3RvbSBkb21haW4gKCR7ZG9tYWlufSlgfVxuICAgICAgICAgIGFjdGlvbj17ZGVwbG95RG9tYWlufVxuICAgICAgICAgIG9uQ29tcGxldGU9e2hhbmRsZURvbWFpbkRlcGxveWVkfVxuICAgICAgICAgIHBlcnNpc3Q9e2ZhbHNlfVxuICAgICAgICAvPlxuICAgICAgKX1cbiAgICAgIHtkb21haW5EZXBsb3llZCAmJiAoXG4gICAgICAgIDxUYXNrXG4gICAgICAgICAgbmFtZT0nVmFsaWRhdGluZyBjdXN0b20gZG9tYWluIEROUydcbiAgICAgICAgICBhY3Rpb249e3ZhbGlkYXRlRG5zfVxuICAgICAgICAgIHBlcnNpc3Q9e2ZhbHNlfVxuICAgICAgICAgIG9uQ29tcGxldGU9e29uRG5zVmFsaWRhdGVkfVxuICAgICAgICAvPlxuICAgICAgKX1cbiAgICAgIHtuYW1lc2VydmVycyAmJiAhZG5zVmFsaWRhdGVkICYmIChcbiAgICAgICAgPEJveCBwYWRkaW5nVG9wPXsxfSBwYWRkaW5nTGVmdD17Mn0+XG4gICAgICAgICAgPFRleHQgY29sb3I9J2dyYXknPlxuICAgICAgICAgICAgQ29uZmlndXJlIHlvdXIgZG9tYWluIHJlZ2lzdHJhciB3aXRoIHRoZSBmb2xsb3dpbmcgbmFtZXNlcnZlcnM6XG4gICAgICAgICAgICA8TmV3bGluZSAvPlxuICAgICAgICAgICAgPE5ld2xpbmUgLz5cbiAgICAgICAgICAgIDxUZXh0IGNvbG9yPSdjeWFuJz57bmFtZXNlcnZlcnMuam9pbignXFxuJyl9PC9UZXh0PlxuICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgPC9Cb3g+XG4gICAgICApfVxuICAgICAge3dlYkRlcGxveWVkICYmIGRuc1ZhbGlkYXRlZCAmJiAoXG4gICAgICAgIDxUYXNrXG4gICAgICAgICAgbmFtZT0nU2V0dGluZyB1cCBTU0wnXG4gICAgICAgICAgYWN0aW9uPXtkZXBsb3lBbGlhc31cbiAgICAgICAgICBvbkNvbXBsZXRlPXtoYW5kbGVBbGlhc0RlcGxveWVkfVxuICAgICAgICAgIHN1Y2Nlc3M9J0ZpbmFsaXppbmcgY3VzdG9tIGRvbWFpbidcbiAgICAgICAgICBwZXJzaXN0PXshbmVlZHNSZWRlcGxveX1cbiAgICAgICAgLz5cbiAgICAgICl9XG4gICAgICB7YWxpYXNEZXBsb3llZCAmJiBuZWVkc1JlZGVwbG95ICYmIChcbiAgICAgICAgPFRhc2sgbmFtZT0nRmluYWxpemluZyBjdXN0b20gZG9tYWluJyBhY3Rpb249e2RlcGxveVdlYn0gb25Db21wbGV0ZT17aGFuZGxlV2ViUmVkZXBsb3llZH0gLz5cbiAgICAgICl9XG4gICAgICB7ZmluaXNoZWQgJiYgKFxuICAgICAgICA8Qm94IHBhZGRpbmdUb3A9ezF9PlxuICAgICAgICAgIDxUZXh0PlxuICAgICAgICAgICAgPFRleHQ+8J+OiSBTaXRlIHN1Y2Nlc3NmdWxseSBkZXBsb3llZDo8L1RleHQ+XG4gICAgICAgICAgICA8TmV3bGluZSAvPlxuICAgICAgICAgICAgPFRleHQ+e3NpdGVVcmx9PC9UZXh0PlxuICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgPC9Cb3g+XG4gICAgICApfVxuICAgICAge2Vycm9yICYmIChcbiAgICAgICAgPEJveCBwYWRkaW5nVG9wPXsxfT5cbiAgICAgICAgICA8VGV4dCBjb2xvcj0ncmVkJz57ZXJyb3J9PC9UZXh0PlxuICAgICAgICA8L0JveD5cbiAgICAgICl9XG4gICAgPC9Cb3g+XG4gIClcbn1cbiJdfQ==