@selfage/generator_cli
Version:
Code generation for message, service, and database.
213 lines • 37.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateService = generateService;
exports.generateRemoteCallsGroup = generateRemoteCallsGroup;
exports.generateRemoteCall = generateRemoteCall;
const output_content_builder_1 = require("./output_content_builder");
const util_1 = require("./util");
let PRIMITIVE_TYPE_BYTES = "bytes";
let PRIMITIVE_TYPES = new Set([PRIMITIVE_TYPE_BYTES]);
function generateService(definitionModulePath, serviceDefinition, outputContentMap) {
let contentBuilder = output_content_builder_1.TsContentBuilder.get(outputContentMap, definitionModulePath);
if (!serviceDefinition.name) {
throw new Error(`"name" is missing on a service.`);
}
if (!serviceDefinition.path) {
throw new Error(`"path" is missing on service ${serviceDefinition.name}.`);
}
contentBuilder.importFromServiceDescriptor(`ServiceDescriptor`);
contentBuilder.push(`
export let ${(0, util_1.toUppercaseSnaked)(serviceDefinition.name)}: ServiceDescriptor = {
name: "${serviceDefinition.name}",
path: "${serviceDefinition.path}",
}
`);
}
function generateRemoteCallsGroup(definitionModulePath, remoteCallsGroupDefinition, definitionResolver, outputContentMap) {
let descriptorContentBuilder = output_content_builder_1.TsContentBuilder.get(outputContentMap, definitionModulePath);
if (!remoteCallsGroupDefinition.service) {
throw new Error(`"service" is missing on remote calls group ${remoteCallsGroupDefinition.name}.`);
}
let definition = definitionResolver.resolve(`When looking for service definition for remote calls group ${remoteCallsGroupDefinition.name},`, remoteCallsGroupDefinition.service, remoteCallsGroupDefinition.importService);
if (definition.kind !== "Service") {
throw new Error(`Service name ${remoteCallsGroupDefinition.service} on remote calls group ${remoteCallsGroupDefinition.name} is not a service.`);
}
let serviceName = (0, util_1.toUppercaseSnaked)(remoteCallsGroupDefinition.service);
descriptorContentBuilder.importFromDefinition(remoteCallsGroupDefinition.importService, serviceName);
if (!remoteCallsGroupDefinition.outputClient) {
throw new Error(`"outputClient" is missing on remote calls group ${remoteCallsGroupDefinition.name}.`);
}
let clientContentBuilder = output_content_builder_1.TsContentBuilder.get(outputContentMap, definitionModulePath, remoteCallsGroupDefinition.outputClient);
if (!remoteCallsGroupDefinition.outputHandler) {
throw new Error(`"outputHandler" is missing on remote calls group ${remoteCallsGroupDefinition.name}.`);
}
let handlerContentBuilder = output_content_builder_1.TsContentBuilder.get(outputContentMap, definitionModulePath, remoteCallsGroupDefinition.outputHandler);
if (!remoteCallsGroupDefinition.calls) {
throw new Error(`"calls" is either missing or not an array on remote calls group ${remoteCallsGroupDefinition.name}.`);
}
for (let remoteCall of remoteCallsGroupDefinition.calls) {
remoteCall.path = (remoteCallsGroupDefinition.path ?? "") + remoteCall.path;
generateRemoteCall(definitionModulePath, remoteCall, serviceName, definitionResolver, descriptorContentBuilder, clientContentBuilder, handlerContentBuilder);
}
}
function generateRemoteCall(definitionModulePath, remoteCallDefinition, serviceName, definitionResolver, descriptorContentBuilder, clientContentBuilder, handlerContentBuilder) {
if (!remoteCallDefinition.name) {
throw new Error(`"name" is missing on a RemoteCall.`);
}
let loggingPrefix = `When generating descriptor for remote call ${remoteCallDefinition.name},`;
let bodyDescriptor = "";
if (!remoteCallDefinition.body) {
throw new Error(`${loggingPrefix} "body" is missing.`);
}
if (PRIMITIVE_TYPES.has(remoteCallDefinition.body)) {
descriptorContentBuilder.importFromServiceDescriptor("PrimitveTypeForBody");
bodyDescriptor = `
body: {
primitiveType: PrimitveTypeForBody.${remoteCallDefinition.body.toUpperCase()},
},`;
}
else {
let requesBodytDefinition = definitionResolver.resolve(loggingPrefix, remoteCallDefinition.body, remoteCallDefinition.importBody);
if (requesBodytDefinition.kind !== "Message") {
throw new Error(`${loggingPrefix} request body ${remoteCallDefinition.body} is not a message.`);
}
let requestBodyDescriptorName = (0, util_1.toUppercaseSnaked)(remoteCallDefinition.body);
descriptorContentBuilder.importFromDefinition(remoteCallDefinition.importBody, requestBodyDescriptorName);
bodyDescriptor = `
body: {
messageType: ${requestBodyDescriptorName},
},`;
}
let metadataDescriptor = "";
if (remoteCallDefinition.metadata) {
if (!remoteCallDefinition.metadata.type) {
throw new Error(`${loggingPrefix} "type" is missing in the "metadata" field.`);
}
let metadataDefinition = definitionResolver.resolve(loggingPrefix, remoteCallDefinition.metadata.type, remoteCallDefinition.metadata.import);
if (metadataDefinition.kind !== "Message") {
throw new Error(`${loggingPrefix} metadata type ${remoteCallDefinition.metadata.type} is not a message.`);
}
let metadataDescriptorName = (0, util_1.toUppercaseSnaked)(remoteCallDefinition.metadata.type);
descriptorContentBuilder.importFromDefinition(remoteCallDefinition.metadata.import, metadataDescriptorName);
if (!remoteCallDefinition.metadata.key) {
throw new Error(`${loggingPrefix} "key" is missing in the "metadata" field.`);
}
metadataDescriptor = `
metadata: {
key: "${remoteCallDefinition.metadata.key}",
type: ${metadataDescriptorName},
},`;
}
let authKey = "";
if (remoteCallDefinition.authKey) {
authKey = `
authKey: "${remoteCallDefinition.authKey}",`;
}
if (!remoteCallDefinition.response) {
throw new Error(`${loggingPrefix} "response" is missing.`);
}
let responseDefinition = definitionResolver.resolve(loggingPrefix, remoteCallDefinition.response, remoteCallDefinition.importResponse);
if (responseDefinition.kind !== "Message") {
throw new Error(`${loggingPrefix} response type ${remoteCallDefinition.response} is not a message.`);
}
let responseDescriptorName = (0, util_1.toUppercaseSnaked)(remoteCallDefinition.response);
descriptorContentBuilder.importFromDefinition(remoteCallDefinition.importResponse, responseDescriptorName);
let responseDescriptor = `
response: {
messageType: ${responseDescriptorName},
},`;
descriptorContentBuilder.importFromServiceDescriptor("RemoteCallDescriptor");
let remoteCallDescriptorName = (0, util_1.toUppercaseSnaked)(remoteCallDefinition.name);
descriptorContentBuilder.push(`
export let ${remoteCallDescriptorName}: RemoteCallDescriptor = {
name: "${remoteCallDefinition.name}",
service: ${serviceName},
path: "${remoteCallDefinition.path}",${bodyDescriptor}${metadataDescriptor}${authKey}${responseDescriptor}
}
`);
generateClient(definitionModulePath, remoteCallDefinition, clientContentBuilder);
generateHandler(definitionModulePath, remoteCallDefinition, handlerContentBuilder);
}
function generateClient(definitionModulePath, remoteCallDefinition, clientContentBuilder) {
let loggingPrefix = `When generating client for ${remoteCallDefinition.name},`;
let bodyParam = "";
if (PRIMITIVE_TYPES.has(remoteCallDefinition.body)) {
if (remoteCallDefinition.body === PRIMITIVE_TYPE_BYTES) {
bodyParam = `
body: Blob,`;
}
else {
throw new Error(`${loggingPrefix} there is a new primitive type needs to be handled for its request body.`);
}
}
else {
clientContentBuilder.importFromDefinition(remoteCallDefinition.importBody, remoteCallDefinition.body);
bodyParam = `
body: ${remoteCallDefinition.body},`;
}
let metadataParam = "";
let metdataVariable = "";
if (remoteCallDefinition.metadata) {
clientContentBuilder.importFromDefinition(remoteCallDefinition.metadata.import, remoteCallDefinition.metadata.type);
metadataParam = `
metadata: ${remoteCallDefinition.metadata.type},`;
metdataVariable = `
metadata,`;
}
clientContentBuilder.importFromDefinition(remoteCallDefinition.importResponse, remoteCallDefinition.response);
let remoteCallDescriptorName = (0, util_1.toUppercaseSnaked)(remoteCallDefinition.name);
clientContentBuilder.importFromDefinition(definitionModulePath, remoteCallDescriptorName);
clientContentBuilder.importFromServiceClientRequestInterface("ClientRequestInterface");
clientContentBuilder.push(`
export function new${remoteCallDefinition.name}Request(${bodyParam}${metadataParam}
): ClientRequestInterface<${remoteCallDefinition.response}> {
return {
descriptor: ${remoteCallDescriptorName},
body,${metdataVariable}
};
}
`);
}
function generateHandler(definitionModulePath, remoteCallDefinition, handlerContentBuilder) {
let loggingPrefix = `When generating handler for ${remoteCallDefinition.name},`;
let bodyParam = "";
if (PRIMITIVE_TYPES.has(remoteCallDefinition.body)) {
if (remoteCallDefinition.body === PRIMITIVE_TYPE_BYTES) {
handlerContentBuilder.importFromStream("Readable");
bodyParam = `
body: Readable,`;
}
else {
throw new Error(`${loggingPrefix} there is a new primitive type needs to be handled for its request body.`);
}
}
else {
handlerContentBuilder.importFromDefinition(remoteCallDefinition.importBody, remoteCallDefinition.body);
bodyParam = `
body: ${remoteCallDefinition.body},`;
}
let metadataParam = "";
if (remoteCallDefinition.metadata) {
handlerContentBuilder.importFromDefinition(remoteCallDefinition.metadata.import, remoteCallDefinition.metadata.type);
metadataParam = `
metadata: ${remoteCallDefinition.metadata.type},`;
}
let authStrParam = "";
if (remoteCallDefinition.authKey) {
authStrParam = `
authStr: string,`;
}
let remoteCallDescriptorName = (0, util_1.toUppercaseSnaked)(remoteCallDefinition.name);
handlerContentBuilder.importFromDefinition(definitionModulePath, remoteCallDescriptorName);
handlerContentBuilder.importFromDefinition(remoteCallDefinition.importResponse, remoteCallDefinition.response);
handlerContentBuilder.importFromServiceRemoteCallHandlerInterface("RemoteCallHandlerInterface");
handlerContentBuilder.push(`
export abstract class ${remoteCallDefinition.name}HandlerInterface implements RemoteCallHandlerInterface {
public descriptor = ${remoteCallDescriptorName};
public abstract handle(
loggingPrefix: string,${bodyParam}${metadataParam}${authStrParam}
): Promise<${remoteCallDefinition.response}>;
}
`);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZV9nZW5lcmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzZXJ2aWNlX2dlbmVyYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQWVBLDBDQXNCQztBQUVELDREQXNFQztBQUVELGdEQW9JQztBQTdPRCxxRUFHa0M7QUFDbEMsaUNBQTJDO0FBRTNDLElBQUksb0JBQW9CLEdBQUcsT0FBTyxDQUFDO0FBQ25DLElBQUksZUFBZSxHQUFHLElBQUksR0FBRyxDQUFTLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDO0FBRTlELFNBQWdCLGVBQWUsQ0FDN0Isb0JBQTRCLEVBQzVCLGlCQUFvQyxFQUNwQyxnQkFBbUQ7SUFFbkQsSUFBSSxjQUFjLEdBQUcseUNBQWdCLENBQUMsR0FBRyxDQUN2QyxnQkFBZ0IsRUFDaEIsb0JBQW9CLENBQ3JCLENBQUM7SUFDRixJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDNUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFDRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDNUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQ0FBZ0MsaUJBQWlCLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUM3RSxDQUFDO0lBQ0QsY0FBYyxDQUFDLDJCQUEyQixDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDaEUsY0FBYyxDQUFDLElBQUksQ0FBQzthQUNULElBQUEsd0JBQWlCLEVBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDO1dBQzNDLGlCQUFpQixDQUFDLElBQUk7V0FDdEIsaUJBQWlCLENBQUMsSUFBSTs7Q0FFaEMsQ0FBQyxDQUFDO0FBQ0gsQ0FBQztBQUVELFNBQWdCLHdCQUF3QixDQUN0QyxvQkFBNEIsRUFDNUIsMEJBQXNELEVBQ3RELGtCQUFzQyxFQUN0QyxnQkFBbUQ7SUFFbkQsSUFBSSx3QkFBd0IsR0FB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QUFDLElBQUksR0FBRyxDQUFDO0lBQ3BELENBQUM7SUFFRCxJQUFJLFlBQVksR0FBRyxFQUFFLENBQUM7SUFDdEIsSUFBSSxvQkFBb0IsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNqQyxZQUFZLEdBQUc7cUJBQ0UsQ0FBQztJQUNwQixDQUFDO0lBRUQsSUFBSSx3QkFBd0IsR0FBRyxJQUFBLHdCQUFpQixFQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVFLHFCQUFxQixDQUFDLG9CQUFvQixDQUN4QyxvQkFBb0IsRUFDcEIsd0JBQXdCLENBQ3pCLENBQUM7SUFDRixxQkFBcUIsQ0FBQyxvQkFBb0IsQ0FDeEMsb0JBQW9CLENBQUMsY0FBYyxFQUNuQyxvQkFBb0IsQ0FBQyxRQUFRLENBQzlCLENBQUM7SUFDRixxQkFBcUIsQ0FBQywyQ0FBMkMsQ0FDL0QsNEJBQTRCLENBQzdCLENBQUM7SUFDRixxQkFBcUIsQ0FBQyxJQUFJLENBQUM7d0JBQ0wsb0JBQW9CLENBQUMsSUFBSTt3QkFDekIsd0JBQXdCOzs0QkFFcEIsU0FBUyxHQUFHLGFBQWEsR0FBRyxZQUFZO2VBQ3JELG9CQUFvQixDQUFDLFFBQVE7O0NBRTNDLENBQUMsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBSZW1vdGVDYWxsRGVmaW5pdGlvbixcbiAgUmVtb3RlQ2FsbHNHcm91cERlZmluaXRpb24sXG4gIFNlcnZpY2VEZWZpbml0aW9uLFxufSBmcm9tIFwiLi9kZWZpbml0aW9uXCI7XG5pbXBvcnQgeyBEZWZpbml0aW9uUmVzb2x2ZXIgfSBmcm9tIFwiLi9kZWZpbml0aW9uX3Jlc29sdmVyXCI7XG5pbXBvcnQge1xuICBPdXRwdXRDb250ZW50QnVpbGRlcixcbiAgVHNDb250ZW50QnVpbGRlcixcbn0gZnJvbSBcIi4vb3V0cHV0X2NvbnRlbnRfYnVpbGRlclwiO1xuaW1wb3J0IHsgdG9VcHBlcmNhc2VTbmFrZWQgfSBmcm9tIFwiLi91dGlsXCI7XG5cbmxldCBQUklNSVRJVkVfVFlQRV9CWVRFUyA9IFwiYnl0ZXNcIjtcbmxldCBQUklNSVRJVkVfVFlQRVMgPSBuZXcgU2V0PHN0cmluZz4oW1BSSU1JVElWRV9UWVBFX0JZVEVTXSk7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZVNlcnZpY2UoXG4gIGRlZmluaXRpb25Nb2R1bGVQYXRoOiBzdHJpbmcsXG4gIHNlcnZpY2VEZWZpbml0aW9uOiBTZXJ2aWNlRGVmaW5pdGlvbixcbiAgb3V0cHV0Q29udGVudE1hcDogTWFwPHN0cmluZywgT3V0cHV0Q29udGVudEJ1aWxkZXI+LFxuKTogdm9pZCB7XG4gIGxldCBjb250ZW50QnVpbGRlciA9IFRzQ29udGVudEJ1aWxkZXIuZ2V0KFxuICAgIG91dHB1dENvbnRlbnRNYXAsXG4gICAgZGVmaW5pdGlvbk1vZHVsZVBhdGgsXG4gICk7XG4gIGlmICghc2VydmljZURlZmluaXRpb24ubmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgXCJuYW1lXCIgaXMgbWlzc2luZyBvbiBhIHNlcnZpY2UuYCk7XG4gIH1cbiAgaWYgKCFzZXJ2aWNlRGVmaW5pdGlvbi5wYXRoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBcInBhdGhcIiBpcyBtaXNzaW5nIG9uIHNlcnZpY2UgJHtzZXJ2aWNlRGVmaW5pdGlvbi5uYW1lfS5gKTtcbiAgfVxuICBjb250ZW50QnVpbGRlci5pbXBvcnRGcm9tU2VydmljZURlc2NyaXB0b3IoYFNlcnZpY2VEZXNjcmlwdG9yYCk7XG4gIGNvbnRlbnRCdWlsZGVyLnB1c2goYFxuZXhwb3J0IGxldCAke3RvVXBwZXJjYXNlU25ha2VkKHNlcnZpY2VEZWZpbml0aW9uLm5hbWUpfTogU2VydmljZURlc2NyaXB0b3IgPSB7XG4gIG5hbWU6IFwiJHtzZXJ2aWNlRGVmaW5pdGlvbi5uYW1lfVwiLFxuICBwYXRoOiBcIiR7c2VydmljZURlZmluaXRpb24ucGF0aH1cIixcbn1cbmApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVSZW1vdGVDYWxsc0dyb3VwKFxuICBkZWZpbml0aW9uTW9kdWxlUGF0aDogc3RyaW5nLFxuICByZW1vdGVDYWxsc0dyb3VwRGVmaW5pdGlvbjogUmVtb3RlQ2FsbHNHcm91cERlZmluaXRpb24sXG4gIGRlZmluaXRpb25SZXNvbHZlcjogRGVmaW5pdGlvblJlc29sdmVyLFxuICBvdXRwdXRDb250ZW50TWFwOiBNYXA8c3RyaW5nLCBPdXRwdXRDb250ZW50QnVpbGRlcj4sXG4pOiB2b2lkIHtcbiAgbGV0IGRlc2NyaXB0b3JDb250ZW50QnVpbGRlciA9IFRzQ29udGVudEJ1aWxkZXIuZ2V0KFxuICAgIG91dHB1dENvbnRlbnRNYXAsXG4gICAgZGVmaW5pdGlvbk1vZHVsZVBhdGgsXG4gICk7XG4gIGlmICghcmVtb3RlQ2FsbHNHcm91cERlZmluaXRpb24uc2VydmljZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBcInNlcnZpY2VcIiBpcyBtaXNzaW5nIG9uIHJlbW90ZSBjYWxscyBncm91cCAke3JlbW90ZUNhbGxzR3JvdXBEZWZpbml0aW9uLm5hbWV9LmAsXG4gICAgKTtcbiAgfVxuICBsZXQgZGVmaW5pdGlvbiA9IGRlZmluaXRpb25SZXNvbHZlci5yZXNvbHZlKFxuICAgIGBXaGVuIGxvb2tpbmcgZm9yIHNlcnZpY2UgZGVmaW5pdGlvbiBmb3IgcmVtb3RlIGNhbGxzIGdyb3VwICR7cmVtb3RlQ2FsbHNHcm91cERlZmluaXRpb24ubmFtZX0sYCxcbiAgICByZW1vdGVDYWxsc0dyb3VwRGVmaW5pdGlvbi5zZXJ2aWNlLFxuICAgIHJlbW90ZUNhbGxzR3JvdXBEZWZpbml0aW9uLmltcG9ydFNlcnZpY2UsXG4gICk7XG4gIGlmIChkZWZpbml0aW9uLmtpbmQgIT09IFwiU2VydmljZVwiKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYFNlcnZpY2UgbmFtZSAke3JlbW90ZUNhbGxzR3JvdXBEZWZpbml0aW9uLnNlcnZpY2V9IG9uIHJlbW90ZSBjYWxscyBncm91cCAke3JlbW90ZUNhbGxzR3JvdXBEZWZpbml0aW9uLm5hbWV9IGlzIG5vdCBhIHNlcnZpY2UuYCxcbiAgICApO1xuICB9XG4gIGxldCBzZXJ2aWNlTmFtZSA9IHRvVXBwZXJjYXNlU25ha2VkKHJlbW90ZUNhbGxzR3JvdXBEZWZpbml0aW9uLnNlcnZpY2UpO1xuICBkZXNjcmlwdG9yQ29udGVudEJ1aWxkZXIuaW1wb3J0RnJvbURlZmluaXRpb24oXG4gICAgcmVtb3RlQ2FsbHNHcm91cERlZmluaXRpb24uaW1wb3J0U2VydmljZSxcbiAgICBzZXJ2aWNlTmFtZSxcbiAgKTtcblxuICBpZiAoIXJlbW90ZUNhbGxzR3JvdXBEZWZpbml0aW9uLm91dHB1dENsaWVudCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBcIm91dHB1dENsaWVudFwiIGlzIG1pc3Npbmcgb24gcmVtb3RlIGNhbGxzIGdyb3VwICR7cmVtb3RlQ2FsbHNHcm91cERlZmluaXRpb24ubmFtZX0uYCxcbiAgICApO1xuICB9XG4gIGxldCBjbGllbnRDb250ZW50QnVpbGRlciA9IFRzQ29udGVudEJ1aWxkZXIuZ2V0KFxuICAgIG91dHB1dENvbnRlbnRNYXAsXG4gICAgZGVmaW5pdGlvbk1vZHVsZVBhdGgsXG4gICAgcmVtb3RlQ2FsbHNHcm91cERlZmluaXRpb24ub3V0cHV0Q2xpZW50LFxuICApO1xuXG4gIGlmICghcmVtb3RlQ2FsbHNHcm91cERlZmluaXRpb24ub3V0cHV0SGFuZGxlcikge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBcIm91dHB1dEhhbmRsZXJcIiBpcyBtaXNzaW5nIG9uIHJlbW90ZSBjYWxscyBncm91cCAke3JlbW90ZUNhbGxzR3JvdXBEZWZpbml0aW9uLm5hbWV9LmAsXG4gICAgKTtcbiAgfVxuICBsZXQgaGFuZGxlckNvbnRlbnRCdWlsZGVyID0gVHNDb250ZW50QnVpbGRlci5nZXQoXG4gICAgb3V0cHV0Q29udGVudE1hcCxcbiAgICBkZWZpbml0aW9uTW9kdWxlUGF0aCxcbiAgICByZW1vdGVDYWxsc0dyb3VwRGVmaW5pdGlvbi5vdXRwdXRIYW5kbGVyLFxuICApO1xuXG4gIGlmICghcmVtb3RlQ2FsbHNHcm91cERlZmluaXRpb24uY2FsbHMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgXCJjYWxsc1wiIGlzIGVpdGhlciBtaXNzaW5nIG9yIG5vdCBhbiBhcnJheSBvbiByZW1vdGUgY2FsbHMgZ3JvdXAgJHtyZW1vdGVDYWxsc0dyb3VwRGVmaW5pdGlvbi5uYW1lfS5gLFxuICAgICk7XG4gIH1cbiAgZm9yIChsZXQgcmVtb3RlQ2FsbCBvZiByZW1vdGVDYWxsc0dyb3VwRGVmaW5pdGlvbi5jYWxscykge1xuICAgIHJlbW90ZUNhbGwucGF0aCA9IChyZW1vdGVDYWxsc0dyb3VwRGVmaW5pdGlvbi5wYXRoID8/IFwiXCIpICsgcmVtb3RlQ2FsbC5wYXRoO1xuICAgIGdlbmVyYXRlUmVtb3RlQ2FsbChcbiAgICAgIGRlZmluaXRpb25Nb2R1bGVQYXRoLFxuICAgICAgcmVtb3RlQ2FsbCxcbiAgICAgIHNlcnZpY2VOYW1lLFxuICAgICAgZGVmaW5pdGlvblJlc29sdmVyLFxuICAgICAgZGVzY3JpcHRvckNvbnRlbnRCdWlsZGVyLFxuICAgICAgY2xpZW50Q29udGVudEJ1aWxkZXIsXG4gICAgICBoYW5kbGVyQ29udGVudEJ1aWxkZXIsXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVSZW1vdGVDYWxsKFxuICBkZWZpbml0aW9uTW9kdWxlUGF0aDogc3RyaW5nLFxuICByZW1vdGVDYWxsRGVmaW5pdGlvbjogUmVtb3RlQ2FsbERlZmluaXRpb24sXG4gIHNlcnZpY2VOYW1lOiBzdHJpbmcsXG4gIGRlZmluaXRpb25SZXNvbHZlcjogRGVmaW5pdGlvblJlc29sdmVyLFxuICBkZXNjcmlwdG9yQ29udGVudEJ1aWxkZXI6IFRzQ29udGVudEJ1aWxkZXIsXG4gIGNsaWVudENvbnRlbnRCdWlsZGVyOiBUc0NvbnRlbnRCdWlsZGVyLFxuICBoYW5kbGVyQ29udGVudEJ1aWxkZXI6IFRzQ29udGVudEJ1aWxkZXIsXG4pOiB2b2lkIHtcbiAgaWYgKCFyZW1vdGVDYWxsRGVmaW5pdGlvbi5uYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBcIm5hbWVcIiBpcyBtaXNzaW5nIG9uIGEgUmVtb3RlQ2FsbC5gKTtcbiAgfVxuICBsZXQgbG9nZ2luZ1ByZWZpeCA9IGBXaGVuIGdlbmVyYXRpbmcgZGVzY3JpcHRvciBmb3IgcmVtb3RlIGNhbGwgJHtyZW1vdGVDYWxsRGVmaW5pdGlvbi5uYW1lfSxgO1xuICBsZXQgYm9keURlc2NyaXB0b3IgPSBcIlwiO1xuICBpZiAoIXJlbW90ZUNhbGxEZWZpbml0aW9uLmJvZHkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bG9nZ2luZ1ByZWZpeH0gXCJib2R5XCIgaXMgbWlzc2luZy5gKTtcbiAgfVxuICBpZiAoUFJJTUlUSVZFX1RZUEVTLmhhcyhyZW1vdGVDYWxsRGVmaW5pdGlvbi5ib2R5KSkge1xuICAgIGRlc2NyaXB0b3JDb250ZW50QnVpbGRlci5pbXBvcnRGcm9tU2VydmljZURlc2NyaXB0b3IoXCJQcmltaXR2ZVR5cGVGb3JCb2R5XCIpO1xuICAgIGJvZHlEZXNjcmlwdG9yID0gYFxuICBib2R5OiB7XG4gICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0dmVUeXBlRm9yQm9keS4ke3JlbW90ZUNhbGxEZWZpbml0aW9uLmJvZHkudG9VcHBlckNhc2UoKX0sXG4gIH0sYDtcbiAgfSBlbHNlIHtcbiAgICBsZXQgcmVxdWVzQm9keXREZWZpbml0aW9uID0gZGVmaW5pdGlvblJlc29sdmVyLnJlc29sdmUoXG4gICAgICBsb2dnaW5nUHJlZml4LFxuICAgICAgcmVtb3RlQ2FsbERlZmluaXRpb24uYm9keSxcbiAgICAgIHJlbW90ZUNhbGxEZWZpbml0aW9uLmltcG9ydEJvZHksXG4gICAgKTtcbiAgICBpZiAocmVxdWVzQm9keXREZWZpbml0aW9uLmtpbmQgIT09IFwiTWVzc2FnZVwiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke2xvZ2dpbmdQcmVmaXh9IHJlcXVlc3QgYm9keSAke3JlbW90ZUNhbGxEZWZpbml0aW9uLmJvZHl9IGlzIG5vdCBhIG1lc3NhZ2UuYCxcbiAgICAgICk7XG4gICAgfVxuICAgIGxldCByZXF1ZXN0Qm9keURlc2NyaXB0b3JOYW1lID0gdG9VcHBlcmNhc2VTbmFrZWQoXG4gICAgICByZW1vdGVDYWxsRGVmaW5pdGlvbi5ib2R5LFxuICAgICk7XG4gICAgZGVzY3JpcHRvckNvbnRlbnRCdWlsZGVyLmltcG9ydEZyb21EZWZpbml0aW9uKFxuICAgICAgcmVtb3RlQ2FsbERlZmluaXRpb24uaW1wb3J0Qm9keSxcbiAgICAgIHJlcXVlc3RCb2R5RGVzY3JpcHRvck5hbWUsXG4gICAgKTtcbiAgICBib2R5RGVzY3JpcHRvciA9IGBcbiAgYm9keToge1xuICAgIG1lc3NhZ2VUeXBlOiAke3JlcXVlc3RCb2R5RGVzY3JpcHRvck5hbWV9LFxuICB9LGA7XG4gIH1cblxuICBsZXQgbWV0YWRhdGFEZXNjcmlwdG9yID0gXCJcIjtcbiAgaWYgKHJlbW90ZUNhbGxEZWZpbml0aW9uLm1ldGFkYXRhKSB7XG4gICAgaWYgKCFyZW1vdGVDYWxsRGVmaW5pdGlvbi5tZXRhZGF0YS50eXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke2xvZ2dpbmdQcmVmaXh9IFwidHlwZVwiIGlzIG1pc3NpbmcgaW4gdGhlIFwibWV0YWRhdGFcIiBmaWVsZC5gLFxuICAgICAgKTtcbiAgICB9XG4gICAgbGV0IG1ldGFkYXRhRGVmaW5pdGlvbiA9IGRlZmluaXRpb25SZXNvbHZlci5yZXNvbHZlKFxuICAgICAgbG9nZ2luZ1ByZWZpeCxcbiAgICAgIHJlbW90ZUNhbGxEZWZpbml0aW9uLm1ldGFkYXRhLnR5cGUsXG4gICAgICByZW1vdGVDYWxsRGVmaW5pdGlvbi5tZXRhZGF0YS5pbXBvcnQsXG4gICAgKTtcbiAgICBpZiAobWV0YWRhdGFEZWZpbml0aW9uLmtpbmQgIT09IFwiTWVzc2FnZVwiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke2xvZ2dpbmdQcmVmaXh9IG1ldGFkYXRhIHR5cGUgJHtyZW1vdGVDYWxsRGVmaW5pdGlvbi5tZXRhZGF0YS50eXBlfSBpcyBub3QgYSBtZXNzYWdlLmAsXG4gICAgICApO1xuICAgIH1cbiAgICBsZXQgbWV0YWRhdGFEZXNjcmlwdG9yTmFtZSA9IHRvVXBwZXJjYXNlU25ha2VkKFxuICAgICAgcmVtb3RlQ2FsbERlZmluaXRpb24ubWV0YWRhdGEudHlwZSxcbiAgICApO1xuICAgIGRlc2NyaXB0b3JDb250ZW50QnVpbGRlci5pbXBvcnRGcm9tRGVmaW5pdGlvbihcbiAgICAgIHJlbW90ZUNhbGxEZWZpbml0aW9uLm1ldGFkYXRhLmltcG9ydCxcbiAgICAgIG1ldGFkYXRhRGVzY3JpcHRvck5hbWUsXG4gICAgKTtcbiAgICBpZiAoIXJlbW90ZUNhbGxEZWZpbml0aW9uLm1ldGFkYXRhLmtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJHtsb2dnaW5nUHJlZml4fSBcImtleVwiIGlzIG1pc3NpbmcgaW4gdGhlIFwibWV0YWRhdGFcIiBmaWVsZC5gLFxuICAgICAgKTtcbiAgICB9XG4gICAgbWV0YWRhdGFEZXNjcmlwdG9yID0gYFxuICBtZXRhZGF0YToge1xuICAgIGtleTogXCIke3JlbW90ZUNhbGxEZWZpbml0aW9uLm1ldGFkYXRhLmtleX1cIixcbiAgICB0eXBlOiAke21ldGFkYXRhRGVzY3JpcHRvck5hbWV9LFxuICB9LGA7XG4gIH1cblxuICBsZXQgYXV0aEtleSA9IFwiXCI7XG4gIGlmIChyZW1vdGVDYWxsRGVmaW5pdGlvbi5hdXRoS2V5KSB7XG4gICAgYXV0aEtleSA9IGBcbiAgYXV0aEtleTogXCIke3JlbW90ZUNhbGxEZWZpbml0aW9uLmF1dGhLZXl9XCIsYDtcbiAgfVxuXG4gIGlmICghcmVtb3RlQ2FsbERlZmluaXRpb24ucmVzcG9uc2UpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bG9nZ2luZ1ByZWZpeH0gXCJyZXNwb25zZVwiIGlzIG1pc3NpbmcuYCk7XG4gIH1cbiAgbGV0IHJlc3BvbnNlRGVmaW5pdGlvbiA9IGRlZmluaXRpb25SZXNvbHZlci5yZXNvbHZlKFxuICAgIGxvZ2dpbmdQcmVmaXgsXG4gICAgcmVtb3RlQ2FsbERlZmluaXRpb24ucmVzcG9uc2UsXG4gICAgcmVtb3RlQ2FsbERlZmluaXRpb24uaW1wb3J0UmVzcG9uc2UsXG4gICk7XG4gIGlmIChyZXNwb25zZURlZmluaXRpb24ua2luZCAhPT0gXCJNZXNzYWdlXCIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgJHtsb2dnaW5nUHJlZml4fSByZXNwb25zZSB0eXBlICR7cmVtb3RlQ2FsbERlZmluaXRpb24ucmVzcG9uc2V9IGlzIG5vdCBhIG1lc3NhZ2UuYCxcbiAgICApO1xuICB9XG4gIGxldCByZXNwb25zZURlc2NyaXB0b3JOYW1lID0gdG9VcHBlcmNhc2VTbmFrZWQocmVtb3RlQ2FsbERlZmluaXRpb24ucmVzcG9uc2UpO1xuICBkZXNjcmlwdG9yQ29udGVudEJ1aWxkZXIuaW1wb3J0RnJvbURlZmluaXRpb24oXG4gICAgcmVtb3RlQ2FsbERlZmluaXRpb24uaW1wb3J0UmVzcG9uc2UsXG4gICAgcmVzcG9uc2VEZXNjcmlwdG9yTmFtZSxcbiAgKTtcbiAgbGV0IHJlc3BvbnNlRGVzY3JpcHRvciA9IGBcbiAgcmVzcG9uc2U6IHtcbiAgICBtZXNzYWdlVHlwZTogJHtyZXNwb25zZURlc2NyaXB0b3JOYW1lfSxcbiAgfSxgO1xuXG4gIGRlc2NyaXB0b3JDb250ZW50QnVpbGRlci5pbXBvcnRGcm9tU2VydmljZURlc2NyaXB0b3IoXCJSZW1vdGVDYWxsRGVzY3JpcHRvclwiKTtcbiAgbGV0IHJlbW90ZUNhbGxEZXNjcmlwdG9yTmFtZSA9IHRvVXBwZXJjYXNlU25ha2VkKHJlbW90ZUNhbGxEZWZpbml0aW9uLm5hbWUpO1xuICBkZXNjcmlwdG9yQ29udGVudEJ1aWxkZXIucHVzaChgXG5leHBvcnQgbGV0ICR7cmVtb3RlQ2FsbERlc2NyaXB0b3JOYW1lfTogUmVtb3RlQ2FsbERlc2NyaXB0b3IgPSB7XG4gIG5hbWU6IFwiJHtyZW1vdGVDYWxsRGVmaW5pdGlvbi5uYW1lfVwiLFxuICBzZXJ2aWNlOiAke3NlcnZpY2VOYW1lfSxcbiAgcGF0aDogXCIke3JlbW90ZUNhbGxEZWZpbml0aW9uLnBhdGh9XCIsJHtib2R5RGVzY3JpcHRvcn0ke21ldGFkYXRhRGVzY3JpcHRvcn0ke2F1dGhLZXl9JHtyZXNwb25zZURlc2NyaXB0b3J9XG59XG5gKTtcblxuICBnZW5lcmF0ZUNsaWVudChcbiAgICBkZWZpbml0aW9uTW9kdWxlUGF0aCxcbiAgICByZW1vdGVDYWxsRGVmaW5pdGlvbixcbiAgICBjbGllbnRDb250ZW50QnVpbGRlcixcbiAgKTtcbiAgZ2VuZXJhdGVIYW5kbGVyKFxuICAgIGRlZmluaXRpb25Nb2R1bGVQYXRoLFxuICAgIHJlbW90ZUNhbGxEZWZpbml0aW9uLFxuICAgIGhhbmRsZXJDb250ZW50QnVpbGRlcixcbiAgKTtcbn1cblxuZnVuY3Rpb24gZ2VuZXJhdGVDbGllbnQoXG4gIGRlZmluaXRpb25Nb2R1bGVQYXRoOiBzdHJpbmcsXG4gIHJlbW90ZUNhbGxEZWZpbml0aW9uOiBSZW1vdGVDYWxsRGVmaW5pdGlvbixcbiAgY2xpZW50Q29udGVudEJ1aWxkZXI6IFRzQ29udGVudEJ1aWxkZXIsXG4pOiB2b2lkIHtcbiAgbGV0IGxvZ2dpbmdQcmVmaXggPSBgV2hlbiBnZW5lcmF0aW5nIGNsaWVudCBmb3IgJHtyZW1vdGVDYWxsRGVmaW5pdGlvbi5uYW1lfSxgO1xuICBsZXQgYm9keVBhcmFtID0gXCJcIjtcbiAgaWYgKFBSSU1JVElWRV9UWVBFUy5oYXMocmVtb3RlQ2FsbERlZmluaXRpb24uYm9keSkpIHtcbiAgICBpZiAocmVtb3RlQ2FsbERlZmluaXRpb24uYm9keSA9PT0gUFJJTUlUSVZFX1RZUEVfQllURVMpIHtcbiAgICAgIGJvZHlQYXJhbSA9IGBcbiAgYm9keTogQmxvYixgO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke2xvZ2dpbmdQcmVmaXh9IHRoZXJlIGlzIGEgbmV3IHByaW1pdGl2ZSB0eXBlIG5lZWRzIHRvIGJlIGhhbmRsZWQgZm9yIGl0cyByZXF1ZXN0IGJvZHkuYCxcbiAgICAgICk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGNsaWVudENvbnRlbnRCdWlsZGVyLmltcG9ydEZyb21EZWZpbml0aW9uKFxuICAgICAgcmVtb3RlQ2FsbERlZmluaXRpb24uaW1wb3J0Qm9keSxcbiAgICAgIHJlbW90ZUNhbGxEZWZpbml0aW9uLmJvZHksXG4gICAgKTtcbiAgICBib2R5UGFyYW0gPSBgXG4gIGJvZHk6ICR7cmVtb3RlQ2FsbERlZmluaXRpb24uYm9keX0sYDtcbiAgfVxuXG4gIGxldCBtZXRhZGF0YVBhcmFtID0gXCJcIjtcbiAgbGV0IG1ldGRhdGFWYXJpYWJsZSA9IFwiXCI7XG4gIGlmIChyZW1vdGVDYWxsRGVmaW5pdGlvbi5tZXRhZGF0YSkge1xuICAgIGNsaWVudENvbnRlbnRCdWlsZGVyLmltcG9ydEZyb21EZWZpbml0aW9uKFxuICAgICAgcmVtb3RlQ2FsbERlZmluaXRpb24ubWV0YWRhdGEuaW1wb3J0LFxuICAgICAgcmVtb3RlQ2FsbERlZmluaXRpb24ubWV0YWRhdGEudHlwZSxcbiAgICApO1xuICAgIG1ldGFkYXRhUGFyYW0gPSBgXG4gIG1ldGFkYXRhOiAke3JlbW90ZUNhbGxEZWZpbml0aW9uLm1ldGFkYXRhLnR5cGV9LGA7XG4gICAgbWV0ZGF0YVZhcmlhYmxlID0gYFxuICAgICAgbWV0YWRhdGEsYDtcbiAgfVxuXG4gIGNsaWVudENvbnRlbnRCdWlsZGVyLmltcG9ydEZyb21EZWZpbml0aW9uKFxuICAgIHJlbW90ZUNhbGxEZWZpbml0aW9uLmltcG9ydFJlc3BvbnNlLFxuICAgIHJlbW90ZUNhbGxEZWZpbml0aW9uLnJlc3BvbnNlLFxuICApO1xuICBsZXQgcmVtb3RlQ2FsbERlc2NyaXB0b3JOYW1lID0gdG9VcHBlcmNhc2VTbmFrZWQocmVtb3RlQ2FsbERlZmluaXRpb24ubmFtZSk7XG4gIGNsaWVudENvbnRlbnRCdWlsZGVyLmltcG9ydEZyb21EZWZpbml0aW9uKFxuICAgIGRlZmluaXRpb25Nb2R1bGVQYXRoLFxuICAgIHJlbW90ZUNhbGxEZXNjcmlwdG9yTmFtZSxcbiAgKTtcbiAgY2xpZW50Q29udGVudEJ1aWxkZXIuaW1wb3J0RnJvbVNlcnZpY2VDbGllbnRSZXF1ZXN0SW50ZXJmYWNlKFxuICAgIFwiQ2xpZW50UmVxdWVzdEludGVyZmFjZVwiLFxuICApO1xuICBjbGllbnRDb250ZW50QnVpbGRlci5wdXNoKGBcbmV4cG9ydCBmdW5jdGlvbiBuZXcke3JlbW90ZUNhbGxEZWZpbml0aW9uLm5hbWV9UmVxdWVzdCgke2JvZHlQYXJhbX0ke21ldGFkYXRhUGFyYW19XG4pOiBDbGllbnRSZXF1ZXN0SW50ZXJmYWNlPCR7cmVtb3RlQ2FsbERlZmluaXRpb24ucmVzcG9uc2V9PiB7XG4gIHJldHVybiB7XG4gICAgZGVzY3JpcHRvcjogJHtyZW1vdGVDYWxsRGVzY3JpcHRvck5hbWV9LFxuICAgIGJvZHksJHttZXRkYXRhVmFyaWFibGV9XG4gIH07XG59XG5gKTtcbn1cblxuZnVuY3Rpb24gZ2VuZXJhdGVIYW5kbGVyKFxuICBkZWZpbml0aW9uTW9kdWxlUGF0aDogc3RyaW5nLFxuICByZW1vdGVDYWxsRGVmaW5pdGlvbjogUmVtb3RlQ2FsbERlZmluaXRpb24sXG4gIGhhbmRsZXJDb250ZW50QnVpbGRlcjogVHNDb250ZW50QnVpbGRlcixcbik6IHZvaWQge1xuICBsZXQgbG9nZ2luZ1ByZWZpeCA9IGBXaGVuIGdlbmVyYXRpbmcgaGFuZGxlciBmb3IgJHtyZW1vdGVDYWxsRGVmaW5pdGlvbi5uYW1lfSxgO1xuICBsZXQgYm9keVBhcmFtID0gXCJcIjtcbiAgaWYgKFBSSU1JVElWRV9UWVBFUy5oYXMocmVtb3RlQ2FsbERlZmluaXRpb24uYm9keSkpIHtcbiAgICBpZiAocmVtb3RlQ2FsbERlZmluaXRpb24uYm9keSA9PT0gUFJJTUlUSVZFX1RZUEVfQllURVMpIHtcbiAgICAgIGhhbmRsZXJDb250ZW50QnVpbGRlci5pbXBvcnRGcm9tU3RyZWFtKFwiUmVhZGFibGVcIik7XG4gICAgICBib2R5UGFyYW0gPSBgXG4gICAgYm9keTogUmVhZGFibGUsYDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJHtsb2dnaW5nUHJlZml4fSB0aGVyZSBpcyBhIG5ldyBwcmltaXRpdmUgdHlwZSBuZWVkcyB0byBiZSBoYW5kbGVkIGZvciBpdHMgcmVxdWVzdCBib2R5LmAsXG4gICAgICApO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBoYW5kbGVyQ29udGVudEJ1aWxkZXIuaW1wb3J0RnJvbURlZmluaXRpb24oXG4gICAgICByZW1vdGVDYWxsRGVmaW5pdGlvbi5pbXBvcnRCb2R5LFxuICAgICAgcmVtb3RlQ2FsbERlZmluaXRpb24uYm9keSxcbiAgICApO1xuICAgIGJvZHlQYXJhbSA9IGBcbiAgICBib2R5OiAke3JlbW90ZUNhbGxEZWZpbml0aW9uLmJvZHl9LGA7XG4gIH1cblxuICBsZXQgbWV0YWRhdGFQYXJhbSA9IFwiXCI7XG4gIGlmIChyZW1vdGVDYWxsRGVmaW5pdGlvbi5tZXRhZGF0YSkge1xuICAgIGhhbmRsZXJDb250ZW50QnVpbGRlci5pbXBvcnRGcm9tRGVmaW5pdGlvbihcbiAgICAgIHJlbW90ZUNhbGxEZWZpbml0aW9uLm1ldGFkYXRhLmltcG9ydCxcbiAgICAgIHJlbW90ZUNhbGxEZWZpbml0aW9uLm1ldGFkYXRhLnR5cGUsXG4gICAgKTtcbiAgICBtZXRhZGF0YVBhcmFtID0gYFxuICAgIG1ldGFkYXRhOiAke3JlbW90ZUNhbGxEZWZpbml0aW9uLm1ldGFkYXRhLnR5cGV9LGA7XG4gIH1cblxuICBsZXQgYXV0aFN0clBhcmFtID0gXCJcIjtcbiAgaWYgKHJlbW90ZUNhbGxEZWZpbml0aW9uLmF1dGhLZXkpIHtcbiAgICBhdXRoU3RyUGFyYW0gPSBgXG4gICAgYXV0aFN0cjogc3RyaW5nLGA7XG4gIH1cblxuICBsZXQgcmVtb3RlQ2FsbERlc2NyaXB0b3JOYW1lID0gdG9VcHBlcmNhc2VTbmFrZWQocmVtb3RlQ2FsbERlZmluaXRpb24ubmFtZSk7XG4gIGhhbmRsZXJDb250ZW50QnVpbGRlci5pbXBvcnRGcm9tRGVmaW5pdGlvbihcbiAgICBkZWZpbml0aW9uTW9kdWxlUGF0aCxcbiAgICByZW1vdGVDYWxsRGVzY3JpcHRvck5hbWUsXG4gICk7XG4gIGhhbmRsZXJDb250ZW50QnVpbGRlci5pbXBvcnRGcm9tRGVmaW5pdGlvbihcbiAgICByZW1vdGVDYWxsRGVmaW5pdGlvbi5pbXBvcnRSZXNwb25zZSxcbiAgICByZW1vdGVDYWxsRGVmaW5pdGlvbi5yZXNwb25zZSxcbiAgKTtcbiAgaGFuZGxlckNvbnRlbnRCdWlsZGVyLmltcG9ydEZyb21TZXJ2aWNlUmVtb3RlQ2FsbEhhbmRsZXJJbnRlcmZhY2UoXG4gICAgXCJSZW1vdGVDYWxsSGFuZGxlckludGVyZmFjZVwiLFxuICApO1xuICBoYW5kbGVyQ29udGVudEJ1aWxkZXIucHVzaChgXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgJHtyZW1vdGVDYWxsRGVmaW5pdGlvbi5uYW1lfUhhbmRsZXJJbnRlcmZhY2UgaW1wbGVtZW50cyBSZW1vdGVDYWxsSGFuZGxlckludGVyZmFjZSB7XG4gIHB1YmxpYyBkZXNjcmlwdG9yID0gJHtyZW1vdGVDYWxsRGVzY3JpcHRvck5hbWV9O1xuICBwdWJsaWMgYWJzdHJhY3QgaGFuZGxlKFxuICAgIGxvZ2dpbmdQcmVmaXg6IHN0cmluZywke2JvZHlQYXJhbX0ke21ldGFkYXRhUGFyYW19JHthdXRoU3RyUGFyYW19XG4gICk6IFByb21pc2U8JHtyZW1vdGVDYWxsRGVmaW5pdGlvbi5yZXNwb25zZX0+O1xufVxuYCk7XG59XG4iXX0=