UNPKG

@rudderstack/integrations-lib

Version:

A comprehensive TypeScript library providing shared utilities, SDKs, and tools for RudderStack integrations and destinations.

374 lines 51.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const axios_1 = __importDefault(require("axios")); const utils_1 = require("./utils"); class SFMC { constructor(authObject) { this.validateAuthObject(authObject); this.authObject = authObject; } // eslint-disable-next-line class-methods-use-this validateAuthObject(authObject) { if (!authObject) { throw new Error('authObject is required. See the readme.'); } const validations = [ { key: 'clientId', type: 'string', required: true }, { key: 'clientSecret', type: 'string', required: true }, { key: 'subDomain', type: 'string', required: true, regex: /^\w{28}$/gm, regexMessage: 'subDomain must be a string of length 28', }, ]; validations.forEach(({ key, type, required, regex, regexMessage }) => { const value = authObject[key]; if (required && !value) { throw new Error(`${key} is missing or invalid`); } if (typeof value !== type) { throw new TypeError(`${key} must be a ${type}`); } if (regex && !regex.test(value)) { throw new Error(regexMessage || `${key} does not match the required format`); } }); return authObject; } /** * This function returns the access token. If the token is expired, it will generate a new token. * @returns {Promise<AuthObject>} It returns the access token or error */ async getAccessToken() { if ((0, utils_1.isExpired)(this.authObject)) { try { await (0, utils_1.getToken)(this.authObject); } catch (e) { throw new Error(`Unable to generate token, with error:${e}`); } } return this.authObject; } /** * This method fetches the fields of a data extension. It requires the data extension id. The method returns the fields of the data extension. If the data extension is not found, it returns a RestError. * @param dataExtensionId Id of the data extension whose fields are to be fetched * @returns */ async getDestinationFields(dataExtensionId) { try { const restHeaders = { Authorization: `Bearer ${(await this.getAccessToken()).access_token}`, }; const requestOptions = { method: 'GET', baseURL: (0, utils_1.getUrl)(this.authObject.subDomain), url: `/data/v1/customobjects/${dataExtensionId}/fields`, headers: restHeaders, }; const resp = await (0, axios_1.default)(requestOptions); return resp.data; } catch (err) { if (axios_1.default.isAxiosError(err)) { const axiosError = err; throw new utils_1.RestError(axiosError); } throw err; } } /** * This method fetches the contact attributes. The method returns the contact attributes. If the contact attributes are not found, it returns a RestError. * @param page Page number * @param pageSize Page size * @returns {Promise<ContactAttributesResponse | RestError>} */ async getContactAttributesItems(page, pageSize) { try { const restHeaders = { Authorization: `Bearer ${(await this.getAccessToken()).access_token}`, }; const requestOptions = { method: 'GET', baseURL: (0, utils_1.getUrl)(this.authObject.subDomain), url: `/contacts/v1/attributeSetDefinitions?$page=${page}&$pageSize=${pageSize}`, headers: restHeaders, }; const resp = await (0, axios_1.default)(requestOptions); return resp.data; } catch (err) { if (axios_1.default.isAxiosError(err)) { const axiosError = err; throw new utils_1.RestError(axiosError); } throw err; } } async getContactAttributes() { const contactAttributes = await SFMC.getAllItemFromPages(this.getContactAttributesItems.bind(this)); return contactAttributes; } /** * This method creates a data extension. It requires the data extension fields. The method returns the data extension created. If the data extension is not created, it returns a RestError. * @param body DataExtension fields * @returns */ async createDataExtension(body) { try { const restHeaders = { Authorization: `Bearer ${(await this.getAccessToken()).access_token}`, }; const requestOptions = { method: 'POST', baseURL: (0, utils_1.getUrl)(this.authObject.subDomain), url: '/data/v1/customobjects', headers: restHeaders, data: body, }; const resp = await (0, axios_1.default)(requestOptions); return resp.data; } catch (err) { throw new utils_1.RestError(err); } } /** * This method fetches the business units. The method returns the business units. If the business units are not found, it returns a SoapError. * @returns */ async getBusinessUnits() { try { const accessToken = (await this.getAccessToken()).access_token; const requestOptions = { method: 'POST', baseURL: `https://${this.authObject.subDomain}.soap.marketingcloudapis.com`, url: '/Service.asmx', headers: { SOAPAction: 'Retrieve', 'Content-Type': 'text/xml', }, data: await (0, utils_1.xmlBuilder)('BusinessUnit', ['name', 'id'], accessToken), }; const resp = await (0, axios_1.default)(requestOptions); const parsedData = (0, utils_1.parseXML)(resp.data); const res = parsedData.RetrieveResponseMsg?.Results; const businessUnits = []; if (res) { const createBusinessUnit = (response) => { const { PartnerProperties } = response; const entry = {}; PartnerProperties.forEach((prop) => { switch (prop.Name) { case 'name': entry.Name = prop.Value; break; case 'id': entry.ID = prop.Value; break; default: throw new utils_1.SoapError(`Unknown property: ${prop}`); } }); return entry; }; if (Array.isArray(res)) { res.forEach((eachRes) => { businessUnits.push(createBusinessUnit(eachRes)); }); } else { businessUnits.push(createBusinessUnit(res)); } return businessUnits; } throw new utils_1.SoapError('No Business Units found'); } catch (err) { throw new utils_1.SoapError(err); } } /** * This method fetches the data folders. It business unit id is provided all data folder under that business id would be retrieved otherwise all the data folder will be retrieved. The method returns the data folders. If the data folders are not found, it returns a SoapError. * @param businessUnitId this is the id of the business unit * @returns */ async getDataFolders(businessUnitId) { try { const accessToken = (await this.getAccessToken()).access_token; const requestOptions = { method: 'POST', baseURL: `https://${this.authObject.subDomain}.soap.marketingcloudapis.com`, url: '/Service.asmx', headers: { SOAPAction: 'Retrieve', 'Content-Type': 'text/xml', }, data: businessUnitId ? await (0, utils_1.xmlBuilder)('DataFolder', ['Name', 'ID', 'ParentFolder.ID'], accessToken, (0, utils_1.parseFilter)({ leftOperand: 'Client.ID', rightOperand: businessUnitId })) : await (0, utils_1.xmlBuilder)('DataFolder', ['Name', 'ID', 'ParentFolder.ID'], accessToken), }; const resp = await (0, axios_1.default)(requestOptions); const parsedData = (0, utils_1.parseXML)(resp.data); const res = parsedData.RetrieveResponseMsg?.Results; const dataFolders = []; if (res) { if (Array.isArray(res)) { res.forEach((eachRes) => { dataFolders.push(eachRes); }); } else { dataFolders.push(res); } return dataFolders; } throw new utils_1.SoapError('No Data Folder found'); } catch (err) { throw new utils_1.SoapError(err); } } /** * This function fetches the data extensions. It the data folder id is provided all the data extension under that data folder will be retrieved otherwise all the data extensions under the access token will be fetched. The method returns the data extensions. If the data extensions are not found, it returns a SoapError. * @param dataFolderId Id of the data folder * @returns */ async getDataExtensions(dataFolderId) { try { const accessToken = (await this.getAccessToken()).access_token; const requestOptions = { method: 'POST', baseURL: `https://${this.authObject.subDomain}.soap.marketingcloudapis.com`, url: '/Service.asmx', headers: { SOAPAction: 'Retrieve', 'Content-Type': 'text/xml', }, data: dataFolderId ? await (0, utils_1.xmlBuilder)('DataExtension', ['NAME', 'ObjectId', 'CategoryId', 'CustomerKey', 'IsSendable'], accessToken, (0, utils_1.parseFilter)({ leftOperand: 'CategoryId', rightOperand: dataFolderId })) : await (0, utils_1.xmlBuilder)('DataExtension', ['NAME', 'ObjectId', 'CategoryId', 'CustomerKey', 'IsSendable'], accessToken), }; const resp = await (0, axios_1.default)(requestOptions); const parsedData = (0, utils_1.parseXML)(resp.data); const res = parsedData.RetrieveResponseMsg?.Results; const dataExtensions = []; if (res) { if (Array.isArray(res)) { res.forEach((eachRes) => { dataExtensions.push(SFMC.mapDataExtension(eachRes)); }); } else { dataExtensions.push(SFMC.mapDataExtension(res)); } return dataExtensions; } throw new utils_1.SoapError('No Data Extension found'); } catch (err) { throw new utils_1.SoapError(err); } } static mapDataExtension(dataExtension) { const getProperty = (props, name) => { const property = props.find((prop) => prop.Name === name); if (!property) { throw new Error(`Missing required property: ${name}`); } return property.Value; }; const { PartnerProperties } = dataExtension; return { ObjectId: getProperty(PartnerProperties, 'ObjectId'), Name: getProperty(PartnerProperties, 'NAME'), CategoryId: getProperty(PartnerProperties, 'CategoryId'), ExternalKey: dataExtension.CustomerKey, IsSendable: dataExtension.IsSendable, }; } /** * This function fetches the data extension by id. It returns the data extension. If the data extension is not found, it returns a RestError. * @param dataExtensionId Id of the data extension * @returns {Promise<DataExtension | RestError>} */ async getDataExtensionById(dataExtensionId) { try { const accessToken = (await this.getAccessToken()).access_token; const requestOptions = { method: 'GET', baseURL: (0, utils_1.getUrl)(this.authObject.subDomain), url: `/data/v1/customobjects/${dataExtensionId}`, headers: { Authorization: `Bearer ${accessToken}`, }, }; const resp = await (0, axios_1.default)(requestOptions); return resp.data; } catch (err) { if (axios_1.default.isAxiosError(err)) { const axiosError = err; throw new utils_1.RestError(axiosError); } throw err; } } /** * This function fetches the event definitions. It returns the event definitions. If the event definitions are not found, it returns a RestError. * @param page Page number * @param pageSize Page size * @returns {Promise<EventDefinitionsResponse | RestError>} */ async getEventDefinitions(page, pageSize) { try { const accessToken = (await this.getAccessToken()).access_token; const requestOptions = { method: 'GET', baseURL: (0, utils_1.getUrl)(this.authObject.subDomain), url: `/interaction/v1/eventDefinitions?$page=${page}&$pageSize=${pageSize}`, headers: { Authorization: `Bearer ${accessToken}`, }, }; const resp = await (0, axios_1.default)(requestOptions); return resp.data; } catch (err) { throw new utils_1.RestError(err); } } /** * This function fetches all the event definitions. It returns the event definitions. If the event definitions are not found, it returns a RestError. * @returns {Promise<EventDefinition[] | RestError>} */ async getAllEventDefinitions() { const eventDefinitions = await SFMC.getAllItemFromPages(this.getEventDefinitions.bind(this)); return eventDefinitions; } static async getAllItemFromPages(getItems, pageSize = 50) { // Get first page to determine total count const firstPage = await getItems(1, pageSize); if (firstPage instanceof utils_1.RestError) { throw firstPage; } const totalPages = Math.ceil(firstPage.count / pageSize); const remainingPages = Array.from({ length: totalPages - 1 }, (_, i) => i + 2); const remainingResults = await Promise.all(remainingPages.map(async (page) => { const result = await getItems(page, pageSize); if (result instanceof utils_1.RestError) { throw result; } return result; })); const allResults = [firstPage, ...remainingResults]; return allResults.flatMap((result) => (result instanceof utils_1.RestError ? [] : result.items)); } } exports.default = SFMC; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2Rrcy9zZm1jL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsa0RBQTBDO0FBa0IxQyxtQ0FTaUI7QUFFakIsTUFBcUIsSUFBSTtJQUd2QixZQUFZLFVBQXNCO1FBQ2hDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNwQyxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztJQUMvQixDQUFDO0lBRUQsa0RBQWtEO0lBQ2xELGtCQUFrQixDQUFDLFVBQWU7UUFDaEMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLENBQUMsQ0FBQztRQUM3RCxDQUFDO1FBRUQsTUFBTSxXQUFXLEdBQUc7WUFDbEIsRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRTtZQUNuRCxFQUFFLEdBQUcsRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO1lBQ3ZEO2dCQUNFLEdBQUcsRUFBRSxXQUFXO2dCQUNoQixJQUFJLEVBQUUsUUFBUTtnQkFDZCxRQUFRLEVBQUUsSUFBSTtnQkFDZCxLQUFLLEVBQUUsWUFBWTtnQkFDbkIsWUFBWSxFQUFFLHlDQUF5QzthQUN4RDtTQUNGLENBQUM7UUFFRixXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRTtZQUNuRSxNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDOUIsSUFBSSxRQUFRLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDdkIsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLEdB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QUFTLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsVUFBVSxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRS9FLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUN4QyxjQUFjLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsRUFBRTtZQUNoQyxNQUFNLE1BQU0sR0FBRyxNQUFNLFFBQVEsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDOUMsSUFBSSxNQUFNLFlBQVksaUJBQVMsRUFBRSxDQUFDO2dCQUNoQyxNQUFNLE1BQU0sQ0FBQztZQUNmLENBQUM7WUFDRCxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDLENBQUMsQ0FDSCxDQUFDO1FBRUYsTUFBTSxVQUFVLEdBQUcsQ0FBQyxTQUFTLEVBQUUsR0FBRyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3BELE9BQU8sVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxNQUFNLFlBQVksaUJBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUMzRixDQUFDO0NBQ0Y7QUF4YUQsdUJBd2FDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGF4aW9zLCB7IEF4aW9zRXJyb3IgfSBmcm9tICdheGlvcyc7XG5pbXBvcnQge1xuICBBdXRoT2JqZWN0LFxuICBCdXNpbmVzc1VuaXQsXG4gIEJ1c2luZXNzVW5pdFJlc3BvbnNlLFxuICBDb250YWN0QXR0cmlidXRlc1Jlc3BvbnNlLFxuICBDcmVhdGVEYXRhRXh0ZW5zaW9uUmVzcG9uc2UsXG4gIERhdGFFeHRlbnNpb24sXG4gIERhdGFFeHRlbnNpb25Cb2R5LFxuICBEYXRhRXh0ZW5zaW9uUmVzcG9uc2UsXG4gIERhdGFGb2xkZXIsXG4gIFNGTUNFcnJvclJlc3BvbnNlLFxuICBFdmVudERlZmluaXRpb24sXG4gIEV2ZW50RGVmaW5pdGlvbnNSZXNwb25zZSxcbiAgQ29udGFjdEF0dHJpYnV0ZXMsXG4gIERhdGFFeHRlbnNpb25QYXJ0bmVyUHJvcGVydHksXG4gIERhdGFFeHRlbnNpb25BcGlSZXNwb25zZSxcbn0gZnJvbSAnLi90eXBlJztcbmltcG9ydCB7XG4gIGdldFVybCxcbiAgaXNFeHBpcmVkLFxuICBwYXJzZUZpbHRlcixcbiAgcGFyc2VYTUwsXG4gIGdldFRva2VuLFxuICBSZXN0RXJyb3IsXG4gIFNvYXBFcnJvcixcbiAgeG1sQnVpbGRlcixcbn0gZnJvbSAnLi91dGlscyc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNGTUMge1xuICBhdXRoT2JqZWN0OiBBdXRoT2JqZWN0O1xuXG4gIGNvbnN0cnVjdG9yKGF1dGhPYmplY3Q6IEF1dGhPYmplY3QpIHtcbiAgICB0aGlzLnZhbGlkYXRlQXV0aE9iamVjdChhdXRoT2JqZWN0KTtcbiAgICB0aGlzLmF1dGhPYmplY3QgPSBhdXRoT2JqZWN0O1xuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcbiAgdmFsaWRhdGVBdXRoT2JqZWN0KGF1dGhPYmplY3Q6IGFueSk6IGFueSB7XG4gICAgaWYgKCFhdXRoT2JqZWN0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2F1dGhPYmplY3QgaXMgcmVxdWlyZWQuIFNlZSB0aGUgcmVhZG1lLicpO1xuICAgIH1cblxuICAgIGNvbnN0IHZhbGlkYXRpb25zID0gW1xuICAgICAgeyBrZXk6ICdjbGllbnRJZCcsIHR5cGU6ICdzdHJpbmcnLCByZXF1aXJlZDogdHJ1ZSB9LFxuICAgICAgeyBrZXk6ICdjbGllbnRTZWNyZXQnLCB0eXBlOiAnc3RyaW5nJywgcmVxdWlyZWQ6IHRydWUgfSxcbiAgICAgIHtcbiAgICAgICAga2V5OiAnc3ViRG9tYWluJyxcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICByZWdleDogL15cXHd7Mjh9JC9nbSxcbiAgICAgICAgcmVnZXhNZXNzYWdlOiAnc3ViRG9tYWluIG11c3QgYmUgYSBzdHJpbmcgb2YgbGVuZ3RoIDI4JyxcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIHZhbGlkYXRpb25zLmZvckVhY2goKHsga2V5LCB0eXBlLCByZXF1aXJlZCwgcmVnZXgsIHJlZ2V4TWVzc2FnZSB9KSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZSA9IGF1dGhPYmplY3Rba2V5XTtcbiAgICAgIGlmIChyZXF1aXJlZCAmJiAhdmFsdWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2tleX0gaXMgbWlzc2luZyBvciBpbnZhbGlkYCk7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSB0eXBlKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYCR7a2V5fSBtdXN0IGJlIGEgJHt0eXBlfWApO1xuICAgICAgfVxuICAgICAgaWYgKHJlZ2V4ICYmICFyZWdleC50ZXN0KHZhbHVlKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IocmVnZXhNZXNzYWdlIHx8IGAke2tleX0gZG9lcyBub3QgbWF0Y2ggdGhlIHJlcXVpcmVkIGZvcm1hdGApO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGF1dGhPYmplY3Q7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBmdW5jdGlvbiByZXR1cm5zIHRoZSBhY2Nlc3MgdG9rZW4uIElmIHRoZSB0b2tlbiBpcyBleHBpcmVkLCBpdCB3aWxsIGdlbmVyYXRlIGEgbmV3IHRva2VuLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxBdXRoT2JqZWN0Pn0gIEl0IHJldHVybnMgdGhlIGFjY2VzcyB0b2tlbiBvciBlcnJvclxuICAgKi9cbiAgYXN5bmMgZ2V0QWNjZXNzVG9rZW4oKSB7XG4gICAgaWYgKGlzRXhwaXJlZCh0aGlzLmF1dGhPYmplY3QpKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBnZXRUb2tlbih0aGlzLmF1dGhPYmplY3QpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBnZW5lcmF0ZSB0b2tlbiwgd2l0aCBlcnJvcjoke2V9YCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmF1dGhPYmplY3Q7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgZmV0Y2hlcyB0aGUgZmllbGRzIG9mIGEgZGF0YSBleHRlbnNpb24uIEl0IHJlcXVpcmVzIHRoZSBkYXRhIGV4dGVuc2lvbiBpZC4gVGhlIG1ldGhvZCByZXR1cm5zIHRoZSBmaWVsZHMgb2YgdGhlIGRhdGEgZXh0ZW5zaW9uLiBJZiB0aGUgZGF0YSBleHRlbnNpb24gaXMgbm90IGZvdW5kLCBpdCByZXR1cm5zIGEgUmVzdEVycm9yLlxuICAgKiBAcGFyYW0gZGF0YUV4dGVuc2lvbklkIElkIG9mIHRoZSBkYXRhIGV4dGVuc2lvbiB3aG9zZSBmaWVsZHMgYXJlIHRvIGJlIGZldGNoZWRcbiAgICogQHJldHVybnNcbiAgICovXG4gIGFzeW5jIGdldERlc3RpbmF0aW9uRmllbGRzKGRhdGFFeHRlbnNpb25JZDogc3RyaW5nKTogUHJvbWlzZTxEYXRhRXh0ZW5zaW9uQm9keSB8IFJlc3RFcnJvcj4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN0SGVhZGVycyA9IHtcbiAgICAgICAgQXV0aG9yaXphdGlvbjogYEJlYXJlciAkeyhhd2FpdCB0aGlzLmdldEFjY2Vzc1Rva2VuKCkpLmFjY2Vzc190b2tlbn1gLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zID0ge1xuICAgICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgICBiYXNlVVJMOiBnZXRVcmwodGhpcy5hdXRoT2JqZWN0LnN1YkRvbWFpbiksXG4gICAgICAgIHVybDogYC9kYXRhL3YxL2N1c3RvbW9iamVjdHMvJHtkYXRhRXh0ZW5zaW9uSWR9L2ZpZWxkc2AsXG4gICAgICAgIGhlYWRlcnM6IHJlc3RIZWFkZXJzLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBheGlvcyhyZXF1ZXN0T3B0aW9ucyk7XG4gICAgICByZXR1cm4gcmVzcC5kYXRhO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGF4aW9zLmlzQXhpb3NFcnJvcihlcnIpKSB7XG4gICAgICAgIGNvbnN0IGF4aW9zRXJyb3IgPSBlcnIgYXMgQXhpb3NFcnJvcjxTRk1DRXJyb3JSZXNwb25zZT47XG4gICAgICAgIHRocm93IG5ldyBSZXN0RXJyb3IoYXhpb3NFcnJvcik7XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIGZldGNoZXMgdGhlIGNvbnRhY3QgYXR0cmlidXRlcy4gVGhlIG1ldGhvZCByZXR1cm5zIHRoZSBjb250YWN0IGF0dHJpYnV0ZXMuIElmIHRoZSBjb250YWN0IGF0dHJpYnV0ZXMgYXJlIG5vdCBmb3VuZCwgaXQgcmV0dXJucyBhIFJlc3RFcnJvci5cbiAgICogQHBhcmFtIHBhZ2UgUGFnZSBudW1iZXJcbiAgICogQHBhcmFtIHBhZ2VTaXplIFBhZ2Ugc2l6ZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxDb250YWN0QXR0cmlidXRlc1Jlc3BvbnNlIHwgUmVzdEVycm9yPn1cbiAgICovXG4gIGFzeW5jIGdldENvbnRhY3RBdHRyaWJ1dGVzSXRlbXMoXG4gICAgcGFnZTogbnVtYmVyLFxuICAgIHBhZ2VTaXplOiBudW1iZXIsXG4gICk6IFByb21pc2U8Q29udGFjdEF0dHJpYnV0ZXNSZXNwb25zZSB8IFJlc3RFcnJvcj4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN0SGVhZGVycyA9IHtcbiAgICAgICAgQXV0aG9yaXphdGlvbjogYEJlYXJlciAkeyhhd2FpdCB0aGlzLmdldEFjY2Vzc1Rva2VuKCkpLmFjY2Vzc190b2tlbn1gLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zID0ge1xuICAgICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgICBiYXNlVVJMOiBnZXRVcmwodGhpcy5hdXRoT2JqZWN0LnN1YkRvbWFpbiksXG4gICAgICAgIHVybDogYC9jb250YWN0cy92MS9hdHRyaWJ1dGVTZXREZWZpbml0aW9ucz8kcGFnZT0ke3BhZ2V9JiRwYWdlU2l6ZT0ke3BhZ2VTaXplfWAsXG4gICAgICAgIGhlYWRlcnM6IHJlc3RIZWFkZXJzLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBheGlvcyhyZXF1ZXN0T3B0aW9ucyk7XG4gICAgICByZXR1cm4gcmVzcC5kYXRhO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGF4aW9zLmlzQXhpb3NFcnJvcihlcnIpKSB7XG4gICAgICAgIGNvbnN0IGF4aW9zRXJyb3IgPSBlcnIgYXMgQXhpb3NFcnJvcjxTRk1DRXJyb3JSZXNwb25zZT47XG4gICAgICAgIHRocm93IG5ldyBSZXN0RXJyb3IoYXhpb3NFcnJvcik7XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZ2V0Q29udGFjdEF0dHJpYnV0ZXMoKTogUHJvbWlzZTxDb250YWN0QXR0cmlidXRlc1tdIHwgUmVzdEVycm9yPiB7XG4gICAgY29uc3QgY29udGFjdEF0dHJpYnV0ZXMgPSBhd2FpdCBTRk1DLmdldEFsbEl0ZW1Gcm9tUGFnZXM8Q29udGFjdEF0dHJpYnV0ZXM+KFxuICAgICAgdGhpcy5nZXRDb250YWN0QXR0cmlidXRlc0l0ZW1zLmJpbmQodGhpcyksXG4gICAgKTtcbiAgICByZXR1cm4gY29udGFjdEF0dHJpYnV0ZXM7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgY3JlYXRlcyBhIGRhdGEgZXh0ZW5zaW9uLiBJdCByZXF1aXJlcyB0aGUgZGF0YSBleHRlbnNpb24gZmllbGRzLiBUaGUgbWV0aG9kIHJldHVybnMgdGhlIGRhdGEgZXh0ZW5zaW9uIGNyZWF0ZWQuIElmIHRoZSBkYXRhIGV4dGVuc2lvbiBpcyBub3QgY3JlYXRlZCwgaXQgcmV0dXJucyBhIFJlc3RFcnJvci5cbiAgICogQHBhcmFtIGJvZHkgRGF0YUV4dGVuc2lvbiBmaWVsZHNcbiAgICogQHJldHVybnNcbiAgICovXG4gIGFzeW5jIGNyZWF0ZURhdGFFeHRlbnNpb24oXG4gICAgYm9keTogRGF0YUV4dGVuc2lvbkJvZHksXG4gICk6IFByb21pc2U8Q3JlYXRlRGF0YUV4dGVuc2lvblJlc3BvbnNlIHwgUmVzdEVycm9yPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3RIZWFkZXJzID0ge1xuICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7KGF3YWl0IHRoaXMuZ2V0QWNjZXNzVG9rZW4oKSkuYWNjZXNzX3Rva2VufWAsXG4gICAgICB9O1xuICAgICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7XG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICBiYXNlVVJMOiBnZXRVcmwodGhpcy5hdXRoT2JqZWN0LnN1YkRvbWFpbiksXG4gICAgICAgIHVybDogJy9kYXRhL3YxL2N1c3RvbW9iamVjdHMnLFxuICAgICAgICBoZWFkZXJzOiByZXN0SGVhZGVycyxcbiAgICAgICAgZGF0YTogYm9keSxcbiAgICAgIH07XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgYXhpb3MocmVxdWVzdE9wdGlvbnMpO1xuICAgICAgcmV0dXJuIHJlc3AuZGF0YTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgdGhyb3cgbmV3IFJlc3RFcnJvcihlcnIpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBmZXRjaGVzIHRoZSBidXNpbmVzcyB1bml0cy4gVGhlIG1ldGhvZCByZXR1cm5zIHRoZSBidXNpbmVzcyB1bml0cy4gSWYgdGhlIGJ1c2luZXNzIHVuaXRzIGFyZSBub3QgZm91bmQsIGl0IHJldHVybnMgYSBTb2FwRXJyb3IuXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBhc3luYyBnZXRCdXNpbmVzc1VuaXRzKCk6IFByb21pc2U8QnVzaW5lc3NVbml0W10gfCBTb2FwRXJyb3I+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYWNjZXNzVG9rZW4gPSAoYXdhaXQgdGhpcy5nZXRBY2Nlc3NUb2tlbigpKS5hY2Nlc3NfdG9rZW47XG4gICAgICBjb25zdCByZXF1ZXN0T3B0aW9ucyA9IHtcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgIGJhc2VVUkw6IGBodHRwczovLyR7dGhpcy5hdXRoT2JqZWN0LnN1YkRvbWFpbn0uc29hcC5tYXJrZXRpbmdjbG91ZGFwaXMuY29tYCxcbiAgICAgICAgdXJsOiAnL1NlcnZpY2UuYXNteCcsXG4gICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICBTT0FQQWN0aW9uOiAnUmV0cmlldmUnLFxuICAgICAgICAgICdDb250ZW50LVR5cGUnOiAndGV4dC94bWwnLFxuICAgICAgICB9LFxuICAgICAgICBkYXRhOiBhd2FpdCB4bWxCdWlsZGVyKCdCdXNpbmVzc1VuaXQnLCBbJ25hbWUnLCAnaWQnXSwgYWNjZXNzVG9rZW4pLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBheGlvcyhyZXF1ZXN0T3B0aW9ucyk7XG4gICAgICBjb25zdCBwYXJzZWREYXRhID0gcGFyc2VYTUwocmVzcC5kYXRhKTtcbiAgICAgIGNvbnN0IHJlcyA9IHBhcnNlZERhdGEuUmV0cmlldmVSZXNwb25zZU1zZz8uUmVzdWx0cyBhc1xuICAgICAgICB8IEJ1c2luZXNzVW5pdFJlc3BvbnNlXG4gICAgICAgIHwgQnVzaW5lc3NVbml0UmVzcG9uc2VbXTtcbiAgICAgIGNvbnN0IGJ1c2luZXNzVW5pdHM6IEJ1c2luZXNzVW5pdFtdID0gW107XG4gICAgICBpZiAocmVzKSB7XG4gICAgICAgIGNvbnN0IGNyZWF0ZUJ1c2luZXNzVW5pdCA9IChyZXNwb25zZTogQnVzaW5lc3NVbml0UmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBjb25zdCB7IFBhcnRuZXJQcm9wZXJ0aWVzIH0gPSByZXNwb25zZTtcbiAgICAgICAgICBjb25zdCBlbnRyeSA9IHt9IGFzIEJ1c2luZXNzVW5pdDtcbiAgICAgICAgICBQYXJ0bmVyUHJvcGVydGllcy5mb3JFYWNoKChwcm9wKSA9PiB7XG4gICAgICAgICAgICBzd2l0Y2ggKHByb3AuTmFtZSkge1xuICAgICAgICAgICAgICBjYXNlICduYW1lJzpcbiAgICAgICAgICAgICAgICBlbnRyeS5OYW1lID0gcHJvcC5WYWx1ZSBhcyBzdHJpbmc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIGNhc2UgJ2lkJzpcbiAgICAgICAgICAgICAgICBlbnRyeS5JRCA9IHByb3AuVmFsdWUgYXMgbnVtYmVyO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBTb2FwRXJyb3IoYFVua25vd24gcHJvcGVydHk6ICR7cHJvcH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gZW50cnk7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVzKSkge1xuICAgICAgICAgIHJlcy5mb3JFYWNoKChlYWNoUmVzKSA9PiB7XG4gICAgICAgICAgICBidXNpbmVzc1VuaXRzLnB1c2goY3JlYXRlQnVzaW5lc3NVbml0KGVhY2hSZXMpKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBidXNpbmVzc1VuaXRzLnB1c2goY3JlYXRlQnVzaW5lc3NVbml0KHJlcykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBidXNpbmVzc1VuaXRzO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IFNvYXBFcnJvcignTm8gQnVzaW5lc3MgVW5pdHMgZm91bmQnKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRocm93IG5ldyBTb2FwRXJyb3IoZXJyKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgZmV0Y2hlcyB0aGUgZGF0YSBmb2xkZXJzLiBJdCBidXNpbmVzcyB1bml0IGlkIGlzIHByb3ZpZGVkIGFsbCBkYXRhIGZvbGRlciB1bmRlciB0aGF0IGJ1c2luZXNzIGlkIHdvdWxkIGJlIHJldHJpZXZlZCBvdGhlcndpc2UgYWxsIHRoZSBkYXRhIGZvbGRlciB3aWxsIGJlIHJldHJpZXZlZC4gVGhlIG1ldGhvZCByZXR1cm5zIHRoZSBkYXRhIGZvbGRlcnMuIElmIHRoZSBkYXRhIGZvbGRlcnMgYXJlIG5vdCBmb3VuZCwgaXQgcmV0dXJucyBhIFNvYXBFcnJvci5cbiAgICogQHBhcmFtIGJ1c2luZXNzVW5pdElkIHRoaXMgaXMgdGhlIGlkIG9mIHRoZSBidXNpbmVzcyB1bml0XG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBhc3luYyBnZXREYXRhRm9sZGVycyhidXNpbmVzc1VuaXRJZD86IHN0cmluZyk6IFByb21pc2U8RGF0YUZvbGRlcltdIHwgU29hcEVycm9yPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGFjY2Vzc1Rva2VuID0gKGF3YWl0IHRoaXMuZ2V0QWNjZXNzVG9rZW4oKSkuYWNjZXNzX3Rva2VuO1xuICAgICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7XG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICBiYXNlVVJMOiBgaHR0cHM6Ly8ke3RoaXMuYXV0aE9iamVjdC5zdWJEb21haW59LnNvYXAubWFya2V0aW5nY2xvdWRhcGlzLmNvbWAsXG4gICAgICAgIHVybDogJy9TZXJ2aWNlLmFzbXgnLFxuICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgU09BUEFjdGlvbjogJ1JldHJpZXZlJyxcbiAgICAgICAgICAnQ29udGVudC1UeXBlJzogJ3RleHQveG1sJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGF0YTogYnVzaW5lc3NVbml0SWRcbiAgICAgICAgICA/IGF3YWl0IHhtbEJ1aWxkZXIoXG4gICAgICAgICAgICAgICdEYXRhRm9sZGVyJyxcbiAgICAgICAgICAgICAgWydOYW1lJywgJ0lEJywgJ1BhcmVudEZvbGRlci5JRCddLFxuICAgICAgICAgICAgICBhY2Nlc3NUb2tlbixcbiAgICAgICAgICAgICAgcGFyc2VGaWx0ZXIoeyBsZWZ0T3BlcmFuZDogJ0NsaWVudC5JRCcsIHJpZ2h0T3BlcmFuZDogYnVzaW5lc3NVbml0SWQgfSksXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiBhd2FpdCB4bWxCdWlsZGVyKCdEYXRhRm9sZGVyJywgWydOYW1lJywgJ0lEJywgJ1BhcmVudEZvbGRlci5JRCddLCBhY2Nlc3NUb2tlbiksXG4gICAgICB9O1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IGF4aW9zKHJlcXVlc3RPcHRpb25zKTtcbiAgICAgIGNvbnN0IHBhcnNlZERhdGEgPSBwYXJzZVhNTChyZXNwLmRhdGEpO1xuICAgICAgY29uc3QgcmVzID0gcGFyc2VkRGF0YS5SZXRyaWV2ZVJlc3BvbnNlTXNnPy5SZXN1bHRzIGFzIERhdGFGb2xkZXIgfCBEYXRhRm9sZGVyW107XG4gICAgICBjb25zdCBkYXRhRm9sZGVyczogRGF0YUZvbGRlcltdID0gW107XG4gICAgICBpZiAocmVzKSB7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJlcykpIHtcbiAgICAgICAgICByZXMuZm9yRWFjaCgoZWFjaFJlcykgPT4ge1xuICAgICAgICAgICAgZGF0YUZvbGRlcnMucHVzaChlYWNoUmVzKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkYXRhRm9sZGVycy5wdXNoKHJlcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRhdGFGb2xkZXJzO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IFNvYXBFcnJvcignTm8gRGF0YSBGb2xkZXIgZm91bmQnKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRocm93IG5ldyBTb2FwRXJyb3IoZXJyKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBmdW5jdGlvbiBmZXRjaGVzIHRoZSBkYXRhIGV4dGVuc2lvbnMuIEl0IHRoZSBkYXRhIGZvbGRlciBpZCBpcyBwcm92aWRlZCBhbGwgdGhlIGRhdGEgZXh0ZW5zaW9uIHVuZGVyIHRoYXQgZGF0YSBmb2xkZXIgd2lsbCBiZSByZXRyaWV2ZWQgb3RoZXJ3aXNlIGFsbCB0aGUgZGF0YSBleHRlbnNpb25zIHVuZGVyIHRoZSBhY2Nlc3MgdG9rZW4gd2lsbCBiZSBmZXRjaGVkLiBUaGUgbWV0aG9kIHJldHVybnMgdGhlIGRhdGEgZXh0ZW5zaW9ucy4gSWYgdGhlIGRhdGEgZXh0ZW5zaW9ucyBhcmUgbm90IGZvdW5kLCBpdCByZXR1cm5zIGEgU29hcEVycm9yLlxuICAgKiBAcGFyYW0gZGF0YUZvbGRlcklkIElkIG9mIHRoZSBkYXRhIGZvbGRlclxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgYXN5bmMgZ2V0RGF0YUV4dGVuc2lvbnMoZGF0YUZvbGRlcklkPzogc3RyaW5nKTogUHJvbWlzZTxEYXRhRXh0ZW5zaW9uW10gfCBTb2FwRXJyb3I+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYWNjZXNzVG9rZW4gPSAoYXdhaXQgdGhpcy5nZXRBY2Nlc3NUb2tlbigpKS5hY2Nlc3NfdG9rZW47XG4gICAgICBjb25zdCByZXF1ZXN0T3B0aW9ucyA9IHtcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgIGJhc2VVUkw6IGBodHRwczovLyR7dGhpcy5hdXRoT2JqZWN0LnN1YkRvbWFpbn0uc29hcC5tYXJrZXRpbmdjbG91ZGFwaXMuY29tYCxcbiAgICAgICAgdXJsOiAnL1NlcnZpY2UuYXNteCcsXG4gICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICBTT0FQQWN0aW9uOiAnUmV0cmlldmUnLFxuICAgICAgICAgICdDb250ZW50LVR5cGUnOiAndGV4dC94bWwnLFxuICAgICAgICB9LFxuICAgICAgICBkYXRhOiBkYXRhRm9sZGVySWRcbiAgICAgICAgICA/IGF3YWl0IHhtbEJ1aWxkZXIoXG4gICAgICAgICAgICAgICdEYXRhRXh0ZW5zaW9uJyxcbiAgICAgICAgICAgICAgWydOQU1FJywgJ09iamVjdElkJywgJ0NhdGVnb3J5SWQnLCAnQ3VzdG9tZXJLZXknLCAnSXNTZW5kYWJsZSddLFxuICAgICAgICAgICAgICBhY2Nlc3NUb2tlbixcbiAgICAgICAgICAgICAgcGFyc2VGaWx0ZXIoeyBsZWZ0T3BlcmFuZDogJ0NhdGVnb3J5SWQnLCByaWdodE9wZXJhbmQ6IGRhdGFGb2xkZXJJZCB9KSxcbiAgICAgICAgICAgIClcbiAgICAgICAgICA6IGF3YWl0IHhtbEJ1aWxkZXIoXG4gICAgICAgICAgICAgICdEYXRhRXh0ZW5zaW9uJyxcbiAgICAgICAgICAgICAgWydOQU1FJywgJ09iamVjdElkJywgJ0NhdGVnb3J5SWQnLCAnQ3VzdG9tZXJLZXknLCAnSXNTZW5kYWJsZSddLFxuICAgICAgICAgICAgICBhY2Nlc3NUb2tlbixcbiAgICAgICAgICAgICksXG4gICAgICB9O1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IGF4aW9zKHJlcXVlc3RPcHRpb25zKTtcbiAgICAgIGNvbnN0IHBhcnNlZERhdGEgPSBwYXJzZVhNTChyZXNwLmRhdGEpO1xuICAgICAgY29uc3QgcmVzID0gcGFyc2VkRGF0YS5SZXRyaWV2ZVJlc3BvbnNlTXNnPy5SZXN1bHRzIGFzXG4gICAgICAgIHwgRGF0YUV4dGVuc2lvblJlc3BvbnNlXG4gICAgICAgIHwgRGF0YUV4dGVuc2lvblJlc3BvbnNlW107XG4gICAgICBjb25zdCBkYXRhRXh0ZW5zaW9uczogRGF0YUV4dGVuc2lvbltdID0gW107XG4gICAgICBpZiAocmVzKSB7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJlcykpIHtcbiAgICAgICAgICByZXMuZm9yRWFjaCgoZWFjaFJlcykgPT4ge1xuICAgICAgICAgICAgZGF0YUV4dGVuc2lvbnMucHVzaChTRk1DLm1hcERhdGFFeHRlbnNpb24oZWFjaFJlcykpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRhdGFFeHRlbnNpb25zLnB1c2goU0ZNQy5tYXBEYXRhRXh0ZW5zaW9uKHJlcykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkYXRhRXh0ZW5zaW9ucztcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBTb2FwRXJyb3IoJ05vIERhdGEgRXh0ZW5zaW9uIGZvdW5kJyk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aHJvdyBuZXcgU29hcEVycm9yKGVycik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgbWFwRGF0YUV4dGVuc2lvbihkYXRhRXh0ZW5zaW9uOiBEYXRhRXh0ZW5zaW9uUmVzcG9uc2UpOiBEYXRhRXh0ZW5zaW9uIHtcbiAgICBjb25zdCBnZXRQcm9wZXJ0eSA9IDxUIGV4dGVuZHMgRGF0YUV4dGVuc2lvblBhcnRuZXJQcm9wZXJ0eT4oXG4gICAgICBwcm9wczogRGF0YUV4dGVuc2lvblBhcnRuZXJQcm9wZXJ0eVtdLFxuICAgICAgbmFtZTogVFsnTmFtZSddLFxuICAgICk6IFRbJ1ZhbHVlJ10gPT4ge1xuICAgICAgY29uc3QgcHJvcGVydHkgPSBwcm9wcy5maW5kKChwcm9wKTogcHJvcCBpcyBUID0+IHByb3AuTmFtZSA9PT0gbmFtZSk7XG4gICAgICBpZiAoIXByb3BlcnR5KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTWlzc2luZyByZXF1aXJlZCBwcm9wZXJ0eTogJHtuYW1lfWApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHByb3BlcnR5LlZhbHVlIGFzIFRbJ1ZhbHVlJ107XG4gICAgfTtcblxuICAgIGNvbnN0IHsgUGFydG5lclByb3BlcnRpZXMgfSA9IGRhdGFFeHRlbnNpb247XG4gICAgcmV0dXJuIHtcbiAgICAgIE9iamVjdElkOiBnZXRQcm9wZXJ0eTxEYXRhRXh0ZW5zaW9uUGFydG5lclByb3BlcnR5PihQYXJ0bmVyUHJvcGVydGllcywgJ09iamVjdElkJykgYXMgc3RyaW5nLFxuICAgICAgTmFtZTogZ2V0UHJvcGVydHk8RGF0YUV4dGVuc2lvblBhcnRuZXJQcm9wZXJ0eT4oUGFydG5lclByb3BlcnRpZXMsICdOQU1FJykgYXMgc3RyaW5nLFxuICAgICAgQ2F0ZWdvcnlJZDogZ2V0UHJvcGVydHk8RGF0YUV4dGVuc2lvblBhcnRuZXJQcm9wZXJ0eT4oXG4gICAgICAgIFBhcnRuZXJQcm9wZXJ0aWVzLFxuICAgICAgICAnQ2F0ZWdvcnlJZCcsXG4gICAgICApIGFzIG51bWJlcixcbiAgICAgIEV4dGVybmFsS2V5OiBkYXRhRXh0ZW5zaW9uLkN1c3RvbWVyS2V5LFxuICAgICAgSXNTZW5kYWJsZTogZGF0YUV4dGVuc2lvbi5Jc1NlbmRhYmxlLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBmdW5jdGlvbiBmZXRjaGVzIHRoZSBkYXRhIGV4dGVuc2lvbiBieSBpZC4gSXQgcmV0dXJucyB0aGUgZGF0YSBleHRlbnNpb24uIElmIHRoZSBkYXRhIGV4dGVuc2lvbiBpcyBub3QgZm91bmQsIGl0IHJldHVybnMgYSBSZXN0RXJyb3IuXG4gICAqIEBwYXJhbSBkYXRhRXh0ZW5zaW9uSWQgSWQgb2YgdGhlIGRhdGEgZXh0ZW5zaW9uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPERhdGFFeHRlbnNpb24gfCBSZXN0RXJyb3I+fVxuICAgKi9cbiAgYXN5bmMgZ2V0RGF0YUV4dGVuc2lvbkJ5SWQoXG4gICAgZGF0YUV4dGVuc2lvbklkOiBzdHJpbmcsXG4gICk6IFByb21pc2U8RGF0YUV4dGVuc2lvbkFwaVJlc3BvbnNlIHwgUmVzdEVycm9yPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGFjY2Vzc1Rva2VuID0gKGF3YWl0IHRoaXMuZ2V0QWNjZXNzVG9rZW4oKSkuYWNjZXNzX3Rva2VuO1xuICAgICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7XG4gICAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICAgIGJhc2VVUkw6IGdldFVybCh0aGlzLmF1dGhPYmplY3Quc3ViRG9tYWluKSxcbiAgICAgICAgdXJsOiBgL2RhdGEvdjEvY3VzdG9tb2JqZWN0cy8ke2RhdGFFeHRlbnNpb25JZH1gLFxuICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke2FjY2Vzc1Rva2VufWAsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IGF4aW9zPERhdGFFeHRlbnNpb25BcGlSZXNwb25zZT4ocmVxdWVzdE9wdGlvbnMpO1xuICAgICAgcmV0dXJuIHJlc3AuZGF0YTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgaWYgKGF4aW9zLmlzQXhpb3NFcnJvcihlcnIpKSB7XG4gICAgICAgIGNvbnN0IGF4aW9zRXJyb3IgPSBlcnIgYXMgQXhpb3NFcnJvcjxTRk1DRXJyb3JSZXNwb25zZT47XG4gICAgICAgIHRocm93IG5ldyBSZXN0RXJyb3IoYXhpb3NFcnJvcik7XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgZnVuY3Rpb24gZmV0Y2hlcyB0aGUgZXZlbnQgZGVmaW5pdGlvbnMuIEl0IHJldHVybnMgdGhlIGV2ZW50IGRlZmluaXRpb25zLiBJZiB0aGUgZXZlbnQgZGVmaW5pdGlvbnMgYXJlIG5vdCBmb3VuZCwgaXQgcmV0dXJucyBhIFJlc3RFcnJvci5cbiAgICogQHBhcmFtIHBhZ2UgUGFnZSBudW1iZXJcbiAgICogQHBhcmFtIHBhZ2VTaXplIFBhZ2Ugc2l6ZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxFdmVudERlZmluaXRpb25zUmVzcG9uc2UgfCBSZXN0RXJyb3I+fVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBnZXRFdmVudERlZmluaXRpb25zKFxuICAgIHBhZ2U6IG51bWJlcixcbiAgICBwYWdlU2l6ZTogbnVtYmVyLFxuICApOiBQcm9taXNlPEV2ZW50RGVmaW5pdGlvbnNSZXNwb25zZSB8IFJlc3RFcnJvcj4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBhY2Nlc3NUb2tlbiA9IChhd2FpdCB0aGlzLmdldEFjY2Vzc1Rva2VuKCkpLmFjY2Vzc190b2tlbjtcblxuICAgICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7XG4gICAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICAgIGJhc2VVUkw6IGdldFVybCh0aGlzLmF1dGhPYmplY3Quc3ViRG9tYWluKSxcbiAgICAgICAgdXJsOiBgL2ludGVyYWN0aW9uL3YxL2V2ZW50RGVmaW5pdGlvbnM/JHBhZ2U9JHtwYWdlfSYkcGFnZVNpemU9JHtwYWdlU2l6ZX1gLFxuICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke2FjY2Vzc1Rva2VufWAsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgYXhpb3MocmVxdWVzdE9wdGlvbnMpO1xuICAgICAgcmV0dXJuIHJlc3AuZGF0YTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgdGhyb3cgbmV3IFJlc3RFcnJvcihlcnIpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGZldGNoZXMgYWxsIHRoZSBldmVudCBkZWZpbml0aW9ucy4gSXQgcmV0dXJucyB0aGUgZXZlbnQgZGVmaW5pdGlvbnMuIElmIHRoZSBldmVudCBkZWZpbml0aW9ucyBhcmUgbm90IGZvdW5kLCBpdCByZXR1cm5zIGEgUmVzdEVycm9yLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxFdmVudERlZmluaXRpb25bXSB8IFJlc3RFcnJvcj59XG4gICAqL1xuICBhc3luYyBnZXRBbGxFdmVudERlZmluaXRpb25zKCk6IFByb21pc2U8RXZlbnREZWZpbml0aW9uW10gfCBSZXN0RXJyb3I+IHtcbiAgICBjb25zdCBldmVudERlZmluaXRpb25zID0gYXdhaXQgU0ZNQy5nZXRBbGxJdGVtRnJvbVBhZ2VzPEV2ZW50RGVmaW5pdGlvbj4oXG4gICAgICB0aGlzLmdldEV2ZW50RGVmaW5pdGlvbnMuYmluZCh0aGlzKSxcbiAgICApO1xuICAgIHJldHVybiBldmVudERlZmluaXRpb25zO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgYXN5bmMgZ2V0QWxsSXRlbUZyb21QYWdlczxUPihcbiAgICBnZXRJdGVtczogKFxuICAgICAgcGFnZTogbnVtYmVyLFxuICAgICAgcGFnZVNpemU6IG51bWJlcixcbiAgICApID0+IFByb21pc2U8eyBpdGVtczogVFtdOyBjb3VudDogbnVtYmVyIH0gfCBSZX