UNPKG

@leosprograms/vf-graphql-holochain

Version:

GraphQL schema bindings for the Holochain implementation of ValueFlows

461 lines 51.7 kB
import { decode } from '@msgpack/msgpack'; import { decodeHashFromBase64, encodeHashToBase64 } from '@holochain/client'; import { getEntryFromStore, addEntryToStore, updateLatestRevision } from './store.js'; export function extractIds(obj) { // extract the ids from the object let id = obj.id; let revisionId = obj.revisionId; let output = { id, revisionId, entry: {} }; let args = { ...obj }; delete args.id; delete args.revisionId; output.entry = args; return output; } export async function getPaginatedCollection(cell, linkFunc, entryFunc, paginated) { const collection = await getCollection(cell, linkFunc, null, paginated); const paginatedCollection = paginateCollection(collection, paginated); return paginatedCollection; } export function paginateCollection(collection, args) { const paginated = collection.map((item) => { return { __typename: 'AgentEdge', cursor: item.id, node: { ...item, __typename: item.agentType } }; }); return { pageInfo: { endCursor: null, hasNextPage: false, hasPreviousPage: false, pageLimit: null, startCursor: null, totalCount: null, }, edges: paginated }; } export async function getCollectionLinks(cell, linkFunc, payload, paginated) { const result = await cell.callZome({ zome_name: 'hrea', fn_name: linkFunc, payload, }); const dedupedLinks = Array.from(result.reduce((map, link) => { const encodedTarget = encodeHashToBase64(link.tag); if (!map.has(encodedTarget) || (map.get(encodedTarget)?.timestamp ?? 0) < link.timestamp) { map.set(encodedTarget, link); } return map; }, new Map()).values()); return dedupedLinks; } export async function getCollection(cell, linkFunc, payload, paginated) { const dedupedLinks = await getCollectionLinks(cell, linkFunc, payload, paginated); // handle pagination if (paginated) { const allLinkTags = dedupedLinks.map((link) => encodeHashToBase64(link.tag)); let sliceBegins = 0; let sliceEnds = dedupedLinks.length; if (paginated?.first) { sliceBegins = Math.max(paginated?.first - 1, sliceBegins); } else if (paginated?.after) { sliceBegins = Math.max((allLinkTags.indexOf(paginated?.after || "") + 1), sliceBegins); } if (paginated?.last) { sliceEnds = Math.min(paginated?.last, sliceEnds); } else if (paginated?.before) { sliceEnds = Math.min(allLinkTags.indexOf(paginated?.before || ""), sliceEnds); } const paginatedLinks = dedupedLinks.slice(sliceBegins, sliceEnds); const entries = await getEntries(cell, paginatedLinks); return entries; } else { const entries = await getEntries(cell, dedupedLinks); return entries; } } export async function getEntries(cell, list) { // for each entry in the list, check the store, and if not found, fetch it let entries = []; let toFetch = []; list.forEach((link) => { const revisionId = encodeHashToBase64(link.target); let entry = getEntryFromStore(revisionId); if (entry) { entries.push(entry); // console.log("======================got entry from store=======================", entry) } else { toFetch.push(revisionId); // console.log("--------------------------fetching entry from zome---------------------", revisionId) } }); if (toFetch.length > 0) { let entriesRes = await cell.callZome({ zome_name: 'hrea', fn_name: 'get_generic_entries', payload: toFetch, }); entriesRes.forEach((res) => { if (res?.entry?.Present) { const decoded = decode(res.entry.Present.entry); const camelCased = snakeToCamel(decoded); const withIds = { ...camelCased, // @ts-ignore id: decoded?.id ? encodeHashToBase64(decoded.id) : encodeHashToBase64(res.signed_action.hashed.hash), revisionId: encodeHashToBase64(res.signed_action.hashed.hash), meta: { retrievedRevision: { id: encodeHashToBase64(res.signed_action.hashed.hash), time: res.signed_action.hashed.content.timestamp, } } }; const withFormattedDates = formatDates(withIds); addEntryToStore(withIds.revisionId, withFormattedDates); updateLatestRevision(withFormattedDates.id, withFormattedDates); entries.push(withFormattedDates); } else { console.log(`No entry for items (${list})`, res); } }); } return entries; } export function formatResItem(resItem, id) { if (!resItem?.entry?.Present?.entry) { return null; } let decoded = decode(resItem.entry.Present.entry); let camel = snakeToCamel(decoded); let withId = { ...camel, id: id, revisionId: encodeHashToBase64(resItem.signed_action.hashed.hash), meta: { retrievedRevision: { id: encodeHashToBase64(resItem.signed_action.hashed.hash), time: resItem.signed_action.hashed.content.timestamp, } } }; let encoded = formatDates(withId); return encoded; } export function snakeToCamelString(str) { // convert a snake_case string to camelCase return str.replace(/_([a-z])/g, function (g) { return g[1].toUpperCase(); }); } export function snakeToCamel(lib) { // Recursively convert all keys from snake_case to camelCase // Do not convert if it's a hash (object with only numeric keys) if (Array.isArray(lib)) { return lib.map(snakeToCamel); } else if (lib !== null && typeof lib === 'object') { // Check if all keys are numeric (hash object) const keys = Object.keys(lib); const allNumeric = keys.length > 0 && keys.every(k => /^\d+$/.test(k)); if (allNumeric) { return lib; } let camel = {}; for (let key in lib) { let camelKey = key.replace(/_([a-z])/g, function (g) { return g[1].toUpperCase(); }); // convert rea_action if (camelKey === "reaAction") { camelKey = "action"; } const value = lib[key]; camel[camelKey] = (typeof value === 'object' && value !== null) ? snakeToCamel(value) : value; } return camel; } return lib; } export function camelToSnake(lib) { // Recursively convert all keys from camelCase to snake_case if (Array.isArray(lib)) { return lib.map(camelToSnake); } else if (lib !== null && typeof lib === 'object') { let snake = {}; for (let key in lib) { let snakeKey = key.replace(/([A-Z])/g, "_$1").toLowerCase(); // convert action if (snakeKey === "action") { snakeKey = "rea_action"; } // turn null values into undefined let value = lib[key] === null ? undefined : lib[key]; // recursively convert objects and arrays if (typeof value === 'object' && value !== null) { value = camelToSnake(value); } snake[snakeKey] = value; } return snake; } return lib; } export function detectQuantityValueField(field) { if (field.has_numerical_value !== undefined && field.has_unit !== undefined) { return true; } return false; } export function decodePotentialQuantityValueField(field) { if (field.hasNumericalValue !== undefined && field.hasUnit !== undefined) { return { has_numerical_value: field.hasNumericalValue, has_unit: field.hasUnit?.id ? field.hasUnit.id : (field.hasUnit ? field.hasUnit : null) }; } return field; } export function findAndDecodeQuantityValueFields(obj) { for (let key in obj) { if (typeof obj[key] === 'object' && obj[key] !== null) { if (obj[key].hasNumericalValue !== undefined && obj[key].hasUnit !== undefined) { obj[key] = decodePotentialQuantityValueField(obj[key]); } } } return obj; } // const dateFields = ['due', 'hasBeginning', 'hasEnd', 'hasPointInTime'] // export function formatDates(obj: any) { // dateFields.forEach(field => { // if (obj[field]) { // obj[field] = new Date(obj[field] / 1000) // } // }) // return obj // } // export function reverseFormatDates(obj: any) { // dateFields.forEach(field => { // if (obj[field]) { // obj[field] = new Date(obj[field]).getTime() * 1000 // } // }) // return obj // } const dateFields = ['due', 'hasBeginning', 'hasEnd', 'hasPointInTime']; export function formatDates(obj) { dateFields.forEach(field => { if (obj[field]) { // Only convert if not already a Date if (!(obj[field] instanceof Date)) { obj[field] = new Date(obj[field] / 1000); } } }); return obj; } export function reverseFormatDates(obj) { dateFields.forEach(field => { if (obj[field]) { // Only convert if not already a number (timestamp) if (obj[field] instanceof Date) { obj[field] = obj[field].getTime() * 1000; } } }); return obj; } export function pluralize(str) { if (str === 'person') { return 'people'; } else if (str.endsWith('s')) { return str + 'es'; } else if (str.endsWith('y')) { return str.slice(0, -1) + 'ies'; } else if (str.endsWith('o')) { return str + 'es'; } else if (str.endsWith('ch')) { return str + 'es'; } else if (str.endsWith('sh')) { return str + 'es'; } else { return str + 's'; } } export function decodeHashFields(obj, hashFields) { hashFields.forEach(field => { if (obj[field]) { const decodedField = decodeHashFromBase64(obj[field]); obj[field] = decodedField; obj[`${field}Id`] = decodedField; } }); return obj; } const actions = { "dropoff": { id: "dropoff", label: "dropoff", resourceEffect: "decrement", onhandEffect: "decrement", inputOutput: "output", pairsWith: "pickup" }, "pickup": { id: "pickup", label: "pickup", resourceEffect: "increment", onhandEffect: "increment", inputOutput: "input", pairsWith: "dropoff" }, "consume": { id: "consume", label: "consume", resourceEffect: "decrement", onhandEffect: "decrement", inputOutput: "input", pairsWith: "notApplicable" }, "use": { id: "use", label: "use", resourceEffect: "noEffect", onhandEffect: "noEffect", inputOutput: "input", pairsWith: "notApplicable" }, "work": { id: "work", label: "work", resourceEffect: "noEffect", onhandEffect: "noEffect", inputOutput: "input", pairsWith: "notApplicable" }, "cite": { id: "cite", label: "cite", resourceEffect: "noEffect", onhandEffect: "noEffect", inputOutput: "input", pairsWith: "notApplicable" }, "produce": { id: "produce", label: "produce", resourceEffect: "increment", onhandEffect: "increment", inputOutput: "output", pairsWith: "notApplicable" }, "accept": { id: "accept", label: "accept", resourceEffect: "noEffect", onhandEffect: "decrement", inputOutput: "input", pairsWith: "modify" }, "modify": { id: "modify", label: "modify", resourceEffect: "noEffect", onhandEffect: "increment", inputOutput: "output", pairsWith: "accept" }, "pass": { id: "pass", label: "pass", resourceEffect: "noEffect", onhandEffect: "noEffect", inputOutput: "output", pairsWith: "accept" }, "fail": { id: "fail", label: "fail", resourceEffect: "noEffect", onhandEffect: "noEffect", inputOutput: "output", pairsWith: "accept" }, "deliver-service": { id: "deliver-service", label: "deliver-service", resourceEffect: "noEffect", onhandEffect: "noEffect", inputOutput: "output", pairsWith: "notApplicable" }, "transfer-all-rights": { id: "transfer-all-rights", label: "transfer-all-rights", resourceEffect: "decrementIncrement", onhandEffect: "noEffect", inputOutput: "notApplicable", pairsWith: "notApplicable" }, "transfer-custody": { id: "transfer-custody", label: "transfer-custody", resourceEffect: "noEffect", onhandEffect: "decrementIncrement", inputOutput: "notApplicable", pairsWith: "notApplicable" }, "transfer": { id: "transfer", label: "transfer", resourceEffect: "decrementIncrement", onhandEffect: "decrementIncrement", inputOutput: "notApplicable", pairsWith: "notApplicable" }, "move": { id: "move", label: "move", resourceEffect: "decrementIncrement", onhandEffect: "decrementIncrement", inputOutput: "notApplicable", pairsWith: "notApplicable" }, "raise": { id: "raise", label: "raise", resourceEffect: "increment", onhandEffect: "increment", inputOutput: "notApplicable", pairsWith: "notApplicable" }, "lower": { id: "lower", label: "lower", resourceEffect: "decrement", onhandEffect: "decrement", inputOutput: "notApplicable", pairsWith: "notApplicable" } }; export function getAction(id) { return actions[id]; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQVUsTUFBTSxrQkFBa0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsa0JBQWtCLEVBQThCLE1BQU0sbUJBQW1CLENBQUE7QUFFeEcsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGVBQWUsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLFlBQVksQ0FBQztBQWN0RixNQUFNLFVBQVUsVUFBVSxDQUFDLEdBQW9CO0lBQzdDLGtDQUFrQztJQUNsQyxJQUFJLEVBQUUsR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFBO0lBQ2YsSUFBSSxVQUFVLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQTtJQUMvQixJQUFJLE1BQU0sR0FBRyxFQUFDLEVBQUUsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBQyxDQUFBO0lBQ3hDLElBQUksSUFBSSxHQUFHLEVBQUUsR0FBRyxHQUFHLEVBQXlCLENBQUE7SUFDNUMsT0FBTyxJQUFJLENBQUMsRUFBRSxDQUFBO0lBQ2QsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFBO0lBQ3RCLE1BQU0sQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFBO0lBQ25CLE9BQU8sTUFBTSxDQUFBO0FBQ2YsQ0FBQztBQUVELE1BQU0sQ0FBQyxLQUFLLFVBQVUsc0JBQXNCLENBQUMsSUFBUyxFQUFFLFFBQWdCLEVBQUUsU0FBaUIsRUFBRSxTQUF1QjtJQUNsSCxNQUFNLFVBQVUsR0FBRyxNQUFNLGFBQWEsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztJQUN4RSxNQUFNLG1CQUFtQixHQUFHLGtCQUFrQixDQUFDLFVBQVUsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUN0RSxPQUFPLG1CQUFtQixDQUFBO0FBQzVCLENBQUM7QUFFRCxNQUFNLFVB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QUUsb0JBQW9CO1FBQ2xDLFdBQVcsRUFBRSxlQUFlO1FBQzVCLFNBQVMsRUFBRSxlQUFlO0tBQzNCO0lBQ0QsTUFBTSxFQUFFO1FBQ04sRUFBRSxFQUFFLE1BQU07UUFDVixLQUFLLEVBQUUsTUFBTTtRQUNiLGNBQWMsRUFBRSxvQkFBb0I7UUFDcEMsWUFBWSxFQUFFLG9CQUFvQjtRQUNsQyxXQUFXLEVBQUUsZUFBZTtRQUM1QixTQUFTLEVBQUUsZUFBZTtLQUMzQjtJQUNELE9BQU8sRUFBRTtRQUNQLEVBQUUsRUFBRSxPQUFPO1FBQ1gsS0FBSyxFQUFFLE9BQU87UUFDZCxjQUFjLEVBQUUsV0FBVztRQUMzQixZQUFZLEVBQUUsV0FBVztRQUN6QixXQUFXLEVBQUUsZUFBZTtRQUM1QixTQUFTLEVBQUUsZUFBZTtLQUMzQjtJQUNELE9BQU8sRUFBRTtRQUNQLEVBQUUsRUFBRSxPQUFPO1FBQ1gsS0FBSyxFQUFFLE9BQU87UUFDZCxjQUFjLEVBQUUsV0FBVztRQUMzQixZQUFZLEVBQUUsV0FBVztRQUN6QixXQUFXLEVBQUUsZUFBZTtRQUM1QixTQUFTLEVBQUUsZUFBZTtLQUMzQjtDQUNGLENBQUE7QUFFRCxNQUFNLFVBQVUsU0FBUyxDQUFDLEVBQVU7SUFDbEMsT0FBTyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUE7QUFDcEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGRlY29kZSwgZW5jb2RlIH0gZnJvbSAnQG1zZ3BhY2svbXNncGFjayc7XG5pbXBvcnQgeyBkZWNvZGVIYXNoRnJvbUJhc2U2NCwgZW5jb2RlSGFzaFRvQmFzZTY0LCB0eXBlIEFjdGlvbkhhc2gsIHR5cGUgTGluayB9IGZyb20gJ0Bob2xvY2hhaW4vY2xpZW50J1xuaW1wb3J0IHsgUGFnaW5nUGFyYW1zIH0gZnJvbSAnLi90eXBlcy5qcydcbmltcG9ydCB7IGdldEVudHJ5RnJvbVN0b3JlLCBhZGRFbnRyeVRvU3RvcmUsIHVwZGF0ZUxhdGVzdFJldmlzaW9uIH0gZnJvbSAnLi9zdG9yZS5qcyc7XG5cbnR5cGUgRXh0cmFjdElkc091dHB1dCA9IHtcbiAgaWQ6IHN0cmluZztcbiAgcmV2aXNpb25JZDogc3RyaW5nO1xuICBlbnRyeTogYW55O1xufVxuXG50eXBlIEV4dHJhY3RJZHNJbnB1dCA9IHtcbiAgaWQ6IHN0cmluZztcbiAgcmV2aXNpb25JZDogc3RyaW5nO1xuICBba2V5OiBzdHJpbmddOiBhbnk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0SWRzKG9iajogRXh0cmFjdElkc0lucHV0KTogRXh0cmFjdElkc091dHB1dCB7XG4gIC8vIGV4dHJhY3QgdGhlIGlkcyBmcm9tIHRoZSBvYmplY3RcbiAgbGV0IGlkID0gb2JqLmlkXG4gIGxldCByZXZpc2lvbklkID0gb2JqLnJldmlzaW9uSWRcbiAgbGV0IG91dHB1dCA9IHtpZCwgcmV2aXNpb25JZCwgZW50cnk6IHt9fVxuICBsZXQgYXJncyA9IHsgLi4ub2JqIH0gYXMgUGFydGlhbDx0eXBlb2Ygb2JqPlxuICBkZWxldGUgYXJncy5pZFxuICBkZWxldGUgYXJncy5yZXZpc2lvbklkXG4gIG91dHB1dC5lbnRyeSA9IGFyZ3NcbiAgcmV0dXJuIG91dHB1dFxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0UGFnaW5hdGVkQ29sbGVjdGlvbihjZWxsOiBhbnksIGxpbmtGdW5jOiBzdHJpbmcsIGVudHJ5RnVuYzogc3RyaW5nLCBwYWdpbmF0ZWQ6IFBhZ2luZ1BhcmFtcykge1xuICBjb25zdCBjb2xsZWN0aW9uID0gYXdhaXQgZ2V0Q29sbGVjdGlvbihjZWxsLCBsaW5rRnVuYywgbnVsbCwgcGFnaW5hdGVkKTtcbiAgY29uc3QgcGFnaW5hdGVkQ29sbGVjdGlvbiA9IHBhZ2luYXRlQ29sbGVjdGlvbihjb2xsZWN0aW9uLCBwYWdpbmF0ZWQpO1xuICByZXR1cm4gcGFnaW5hdGVkQ29sbGVjdGlvblxufVxuICBcbmV4cG9ydCBmdW5jdGlvbiBwYWdpbmF0ZUNvbGxlY3Rpb24oY29sbGVjdGlvbjogYW55LCBhcmdzOiBQYWdpbmdQYXJhbXMpIHtcbiAgY29uc3QgcGFnaW5hdGVkID0gY29sbGVjdGlvbi5tYXAoKGl0ZW06IGFueSkgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBfX3R5cGVuYW1lOiAnQWdlbnRFZGdlJyxcbiAgICAgICAgICBjdXJzb3I6IGl0ZW0uaWQsXG4gICAgICAgICAgbm9kZToge1xuICAgICAgICAgICAgICAuLi5pdGVtLFxuICAgICAgICAgICAgICBfX3R5cGVuYW1lOiBpdGVtLmFnZW50VHlwZVxuICAgICAgICAgIH1cbiAgICAgIH1cbiAgfSlcbiAgcmV0dXJuIHtcbiAgICAgIHBhZ2VJbmZvOiB7XG4gICAgICAgICAgZW5kQ3Vyc29yOiBudWxsLFxuICAgICAgICAgIGhhc05leHRQYWdlOiBmYWxzZSxcbiAgICAgICAgICBoYXNQcmV2aW91c1BhZ2U6IGZhbHNlLFxuICAgICAgICAgIHBhZ2VMaW1pdDogbnVsbCxcbiAgICAgICAgICBzdGFydEN1cnNvcjogbnVsbCxcbiAgICAgICAgICB0b3RhbENvdW50OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGVkZ2VzOiBwYWdpbmF0ZWRcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0Q29sbGVjdGlvbkxpbmtzKFxuICBjZWxsOiBhbnksIFxuICBsaW5rRnVuYzogc3RyaW5nLCBcbiAgcGF5bG9hZDogYW55LCBcbiAgcGFnaW5hdGVkPzogUGFnaW5nUGFyYW1zXG4pIHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjZWxsLmNhbGxab21lKHtcbiAgICAgICAgem9tZV9uYW1lOiAnaHJlYScsXG4gICAgICAgIGZuX25hbWU6IGxpbmtGdW5jLFxuICAgICAgICBwYXlsb2FkLFxuICAgIH0pXG4gICAgY29uc3QgZGVkdXBlZExpbmtzOiBBcnJheTxMaW5rPiA9IEFycmF5LmZyb20oXG4gICAgICAgIHJlc3VsdC5yZWR1Y2UoKG1hcDogTWFwPHN0cmluZywgTGluaz4sIGxpbms6IExpbmspID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVuY29kZWRUYXJnZXQgPSBlbmNvZGVIYXNoVG9CYXNlNjQobGluay50YWcpO1xuICAgICAgICAgICAgaWYgKCFtYXAuaGFzKGVuY29kZWRUYXJnZXQpIHx8IChtYXAuZ2V0KGVuY29kZWRUYXJnZXQpPy50aW1lc3RhbXAgPz8gMCkgPCBsaW5rLnRpbWVzdGFtcCkge1xuICAgICAgICAgICAgICAgIG1hcC5zZXQoZW5jb2RlZFRhcmdldCwgbGluayk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWFwO1xuICAgICAgICB9LCBuZXcgTWFwKCkpLnZhbHVlcygpXG4gICAgKTtcbiAgICByZXR1cm4gZGVkdXBlZExpbmtzXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRDb2xsZWN0aW9uKFxuICBjZWxsOiBhbnksIFxuICBsaW5rRnVuYzogc3RyaW5nLCBcbiAgcGF5bG9hZDogYW55LCBcbiAgcGFnaW5hdGVkPzogUGFnaW5nUGFyYW1zXG4pIHtcbiAgICBjb25zdCBkZWR1cGVkTGlua3MgPSBhd2FpdCBnZXRDb2xsZWN0aW9uTGlua3MoY2VsbCwgbGlua0Z1bmMsIHBheWxvYWQsIHBhZ2luYXRlZCk7XG5cbiAgICAvLyBoYW5kbGUgcGFnaW5hdGlvblxuICAgIGlmIChwYWdpbmF0ZWQpIHtcbiAgICAgIGNvbnN0IGFsbExpbmtUYWdzID0gZGVkdXBlZExpbmtzLm1hcCgobGluazogTGluaykgPT4gZW5jb2RlSGFzaFRvQmFzZTY0KGxpbmsudGFnKSlcbiAgICAgIGxldCBzbGljZUJlZ2lucyA9IDBcbiAgICAgIGxldCBzbGljZUVuZHMgPSBkZWR1cGVkTGlua3MubGVuZ3RoXG4gICAgICBpZiAocGFnaW5hdGVkPy5maXJzdCkge1xuICAgICAgICBzbGljZUJlZ2lucyA9IE1hdGgubWF4KHBhZ2luYXRlZD8uZmlyc3QgLSAxLCBzbGljZUJlZ2lucylcbiAgICAgIH0gZWxzZSBpZiAocGFnaW5hdGVkPy5hZnRlcikge1xuICAgICAgICBzbGljZUJlZ2lucyA9IE1hdGgubWF4KChhbGxMaW5rVGFncy5pbmRleE9mKHBhZ2luYXRlZD8uYWZ0ZXIgfHwgXCJcIikgKyAxKSwgc2xpY2VCZWdpbnMpXG4gICAgICB9XG4gICAgICBpZiAocGFnaW5hdGVkPy5sYXN0KSB7XG4gICAgICAgIHNsaWNlRW5kcyA9IE1hdGgubWluKHBhZ2luYXRlZD8ubGFzdCwgc2xpY2VFbmRzKVxuICAgICAgfSBlbHNlIGlmIChwYWdpbmF0ZWQ/LmJlZm9yZSkge1xuICAgICAgICBzbGljZUVuZHMgPSBNYXRoLm1pbihhbGxMaW5rVGFncy5pbmRleE9mKHBhZ2luYXRlZD8uYmVmb3JlIHx8IFwiXCIpLCBzbGljZUVuZHMpXG4gICAgICB9XG4gICAgICBcbiAgICAgIGNvbnN0IHBhZ2luYXRlZExpbmtzID0gZGVkdXBlZExpbmtzLnNsaWNlKHNsaWNlQmVnaW5zLCBzbGljZUVuZHMpXG4gICAgICBjb25zdCBlbnRyaWVzID0gYXdhaXQgZ2V0RW50cmllcyhjZWxsLCBwYWdpbmF0ZWRMaW5rcyk7XG4gICAgICByZXR1cm4gZW50cmllc1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBlbnRyaWVzID0gYXdhaXQgZ2V0RW50cmllcyhjZWxsLCBkZWR1cGVkTGlua3MpO1xuICAgICAgcmV0dXJuIGVudHJpZXNcbiAgICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRFbnRyaWVzKGNlbGw6IGFueSwgbGlzdDogTGlua1tdKSB7XG4gIC8vIGZvciBlYWNoIGVudHJ5IGluIHRoZSBsaXN0LCBjaGVjayB0aGUgc3RvcmUsIGFuZCBpZiBub3QgZm91bmQsIGZldGNoIGl0XG4gIGxldCBlbnRyaWVzOiBhbnlbXSA9IFtdXG4gIGxldCB0b0ZldGNoOiBzdHJpbmdbXSA9IFtdXG5cbiAgbGlzdC5mb3JFYWNoKChsaW5rKSA9PiB7XG4gICAgY29uc3QgcmV2aXNpb25JZCA9IGVuY29kZUhhc2hUb0Jhc2U2NChsaW5rLnRhcmdldClcbiAgICBsZXQgZW50cnkgPSBnZXRFbnRyeUZyb21TdG9yZShyZXZpc2lvbklkKVxuICAgIGlmIChlbnRyeSkge1xuICAgICAgZW50cmllcy5wdXNoKGVudHJ5KVxuICAgICAgLy8gY29uc29sZS5sb2coXCI9PT09PT09PT09PT09PT09PT09PT09Z290IGVudHJ5IGZyb20gc3RvcmU9PT09PT09PT09PT09PT09PT09PT09PVwiLCBlbnRyeSlcbiAgICB9IGVsc2Uge1xuICAgICAgdG9GZXRjaC5wdXNoKHJldmlzaW9uSWQpXG4gICAgICAvLyBjb25zb2xlLmxvZyhcIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tZmV0Y2hpbmcgZW50cnkgZnJvbSB6b21lLS0tLS0tLS0tLS0tLS0tLS0tLS0tXCIsIHJldmlzaW9uSWQpXG4gICAgfVxuICB9KVxuXG4gIGlmICh0b0ZldGNoLmxlbmd0aCA+IDApIHtcbiAgICBsZXQgZW50cmllc1JlcyA9IGF3YWl0IGNlbGwuY2FsbFpvbWUoe1xuICAgICAgem9tZV9uYW1lOiAnaHJlYScsXG4gICAgICBmbl9uYW1lOiAnZ2V0X2dlbmVyaWNfZW50cmllcycsXG4gICAgICBwYXlsb2FkOiB0b0ZldGNoLFxuICAgIH0pXG5cbiAgICBlbnRyaWVzUmVzLmZvckVhY2goKHJlczogYW55KSA9PiB7XG4gICAgICBpZiAocmVzPy5lbnRyeT8uUHJlc2VudCkge1xuICAgICAgICBjb25zdCBkZWNvZGVkID0gZGVjb2RlKHJlcy5lbnRyeS5QcmVzZW50LmVudHJ5KVxuICAgICAgICBjb25zdCBjYW1lbENhc2VkID0gc25ha2VUb0NhbWVsKGRlY29kZWQpXG4gICAgICAgIGNvbnN0IHdpdGhJZHMgPSB7XG4gICAgICAgICAgLi4uY2FtZWxDYXNlZCwgXG4gICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgIGlkOiBkZWNvZGVkPy5pZCA/IGVuY29kZUhhc2hUb0Jhc2U2NChkZWNvZGVkLmlkKSA6IGVuY29kZUhhc2hUb0Jhc2U2NChyZXMuc2lnbmVkX2FjdGlvbi5oYXNoZWQuaGFzaCksIFxuICAgICAgICAgIHJldmlzaW9uSWQ6IGVuY29kZUhhc2hUb0Jhc2U2NChyZXMuc2lnbmVkX2FjdGlvbi5oYXNoZWQuaGFzaCksXG4gICAgICAgICAgbWV0YToge1xuICAgICAgICAgICAgcmV0cmlldmVkUmV2aXNpb246IHtcbiAgICAgICAgICAgICAgaWQ6IGVuY29kZUhhc2hUb0Jhc2U2NChyZXMuc2lnbmVkX2FjdGlvbi5oYXNoZWQuaGFzaCksXG4gICAgICAgICAgICAgIHRpbWU6IHJlcy5zaWduZWRfYWN0aW9uLmhhc2hlZC5jb250ZW50LnRpbWVzdGFtcCxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgd2l0aEZvcm1hdHRlZERhdGVzID0gZm9ybWF0RGF0ZXMod2l0aElkcylcbiAgICAgICAgYWRkRW50cnlUb1N0b3JlKHdpdGhJZHMucmV2aXNpb25JZCwgd2l0aEZvcm1hdHRlZERhdGVzKVxuICAgICAgICB1cGRhdGVMYXRlc3RSZXZpc2lvbihcbiAgICAgICAgICB3aXRoRm9ybWF0dGVkRGF0ZXMuaWQsXG4gICAgICAgICAgd2l0aEZvcm1hdHRlZERhdGVzXG4gICAgICAgIClcbiAgICAgICAgZW50cmllcy5wdXNoKHdpdGhGb3JtYXR0ZWREYXRlcylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBObyBlbnRyeSBmb3IgaXRlbXMgKCR7bGlzdH0pYCwgcmVzKVxuICAgICAgfVxuICAgIH0pXG4gIH1cbiAgcmV0dXJuIGVudHJpZXNcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFJlc0l0ZW0ocmVzSXRlbTogYW55LCBpZDogQWN0aW9uSGFzaCkge1xuICBpZiAoIXJlc0l0ZW0/LmVudHJ5Py5QcmVzZW50Py5lbnRyeSkgeyByZXR1cm4gbnVsbCB9XG4gIGxldCBkZWNvZGVkID0gZGVjb2RlKHJlc0l0ZW0uZW50cnkuUHJlc2VudC5lbnRyeSlcbiAgbGV0IGNhbWVsID0gc25ha2VUb0NhbWVsKGRlY29kZWQpXG4gIGxldCB3aXRoSWQgPSB7XG4gICAgLi4uY2FtZWwsIFxuICAgIGlkOiAgaWQsXG4gICAgcmV2aXNpb25JZDogZW5jb2RlSGFzaFRvQmFzZTY0KHJlc0l0ZW0uc2lnbmVkX2FjdGlvbi5oYXNoZWQuaGFzaCksXG4gICAgbWV0YToge1xuICAgICAgcmV0cmlldmVkUmV2aXNpb246IHtcbiAgICAgICAgaWQ6IGVuY29kZUhhc2hUb0Jhc2U2NChyZXNJdGVtLnNpZ25lZF9hY3Rpb24uaGFzaGVkLmhhc2gpLFxuICAgICAgICB0aW1lOiByZXNJdGVtLnNpZ25lZF9hY3Rpb24uaGFzaGVkLmNvbnRlbnQudGltZXN0YW1wLFxuICAgICAgfVxuICAgIH1cbiAgfVxuICBsZXQgZW5jb2RlZCA9IGZvcm1hdERhdGVzKHdpdGhJZClcbiAgcmV0dXJuIGVuY29kZWRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNuYWtlVG9DYW1lbFN0cmluZyhzdHI6IHN0cmluZykge1xuICAvLyBjb252ZXJ0IGEgc25ha2VfY2FzZSBzdHJpbmcgdG8gY2FtZWxDYXNlXG4gIHJldHVybiBzdHIucmVwbGFjZSgvXyhbYS16XSkvZywgZnVuY3Rpb24gKGcpIHsgcmV0dXJuIGdbMV0udG9VcHBlckNhc2UoKTsgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzbmFrZVRvQ2FtZWwobGliOiBhbnkpOiBhbnkge1xuICAvLyBSZWN1cnNpdmVseSBjb252ZXJ0IGFsbCBrZXlzIGZyb20gc25ha2VfY2FzZSB0byBjYW1lbENhc2VcbiAgLy8gRG8gbm90IGNvbnZlcnQgaWYgaXQncyBhIGhhc2ggKG9iamVjdCB3aXRoIG9ubHkgbnVtZXJpYyBrZXlzKVxuICBpZiAoQXJyYXkuaXNBcnJheShsaWIpKSB7XG4gICAgcmV0dXJuIGxpYi5tYXAoc25ha2VUb0NhbWVsKTtcbiAgfSBlbHNlIGlmIChsaWIgIT09IG51bGwgJiYgdHlwZW9mIGxpYiA9PT0gJ29iamVjdCcpIHtcbiAgICAvLyBDaGVjayBpZiBhbGwga2V5cyBhcmUgbnVtZXJpYyAoaGFzaCBvYmplY3QpXG4gICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGxpYik7XG4gICAgY29uc3QgYWxsTnVtZXJpYyA9IGtleXMubGVuZ3RoID4gMCAmJiBrZXlzLmV2ZXJ5KGsgPT4gL15cXGQrJC8udGVzdChrKSk7XG4gICAgaWYgKGFsbE51bWVyaWMpIHtcbiAgICAgIHJldHVybiBsaWI7XG4gICAgfVxuICAgIGxldCBjYW1lbDogYW55ID0ge307XG4gICAgZm9yIChsZXQga2V5IGluIGxpYikge1xuICAgICAgbGV0IGNhbWVsS2V5ID0ga2V5LnJlcGxhY2UoL18oW2Etel0pL2csIGZ1bmN0aW9uIChnKSB7IHJldHVybiBnWzFdLnRvVXBwZXJDYXNlKCk7IH0pO1xuICAgICAgLy8gY29udmVydCByZWFfYWN0aW9uXG4gICAgICBpZiAoY2FtZWxLZXkgPT09IFwicmVhQWN0aW9uXCIpIHtcbiAgICAgICAgY2FtZWxLZXkgPSBcImFjdGlvblwiO1xuICAgICAgfVxuICAgICAgY29uc3QgdmFsdWUgPSBsaWJba2V5XTtcbiAgICAgIGNhbWVsW2NhbWVsS2V5XSA9ICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsKVxuICAgICAgICA/IHNuYWtlVG9DYW1lbCh2YWx1ZSlcbiAgICAgICAgOiB2YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGNhbWVsO1xuICB9XG4gIHJldHVybiBsaWI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjYW1lbFRvU25ha2UobGliOiBhbnkpOiBhbnkge1xuICAvLyBSZWN1cnNpdmVseSBjb252ZXJ0IGFsbCBrZXlzIGZyb20gY2FtZWxDYXNlIHRvIHNuYWtlX2Nhc2VcbiAgaWYgKEFycmF5LmlzQXJyYXkobGliKSkge1xuICAgIHJldHVybiBsaWIubWFwKGNhbWVsVG9TbmFrZSk7XG4gIH0gZWxzZSBpZiAobGliICE9PSBudWxsICYmIHR5cGVvZiBsaWIgPT09ICdvYmplY3QnKSB7XG4gICAgbGV0IHNuYWtlOiBhbnkgPSB7fTtcbiAgICBmb3IgKGxldCBrZXkgaW4gbGliKSB7XG4gICAgICBsZXQgc25ha2VLZXkgPSBrZXkucmVwbGFjZSgvKFtBLVpdKS9nLCBcIl8kMVwiKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgLy8gY29udmVydCBhY3Rpb25cbiAgICAgIGlmIChzbmFrZUtleSA9PT0gXCJhY3Rpb25cIikge1xuICAgICAgICBzbmFrZUtleSA9IFwicmVhX2FjdGlvblwiO1xuICAgICAgfVxuICAgICAgLy8gdHVybiBudWxsIHZhbHVlcyBpbnRvIHVuZGVmaW5lZFxuICAgICAgbGV0IHZhbHVlID0gbGliW2tleV0gPT09IG51bGwgPyB1bmRlZmluZWQgOiBsaWJba2V5XTtcbiAgICAgIC8vIHJlY3Vyc2l2ZWx5IGNvbnZlcnQgb2JqZWN0cyBhbmQgYXJyYXlzXG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCkge1xuICAgICAgICB2YWx1ZSA9IGNhbWVsVG9TbmFrZSh2YWx1ZSk7XG4gICAgICB9XG4gICAgICBzbmFrZVtzbmFrZUtleV0gPSB2YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHNuYWtlO1xuICB9XG4gIHJldHVybiBsaWI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZXRlY3RRdWFudGl0eVZhbHVlRmllbGQoZmllbGQ6IGFueSkge1xuICBpZiAoZmllbGQuaGFzX251bWVyaWNhbF92YWx1ZSAhPT0gdW5kZWZpbmVkICYmIGZpZWxkLmhhc191bml0ICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gdHJ1ZVxuICB9XG4gIHJldHVybiBmYWxzZVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlUG90ZW50aWFsUXVhbnRpdHlWYWx1ZUZpZWxkKGZpZWxkOiBhbnkpIHtcbiAgaWYgKGZpZWxkLmhhc051bWVyaWNhbFZhbHVlICE9PSB1bmRlZmluZWQgJiYgZmllbGQuaGFzVW5pdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGhhc19udW1lcmljYWxfdmFsdWU6IGZpZWxkLmhhc051bWVyaWNhbFZhbHVlLFxuICAgICAgaGFzX3VuaXQ6IGZpZWxkLmhhc1VuaXQ/LmlkID8gZmllbGQuaGFzVW5pdC5pZCA6IChmaWVsZC5oYXNVbml0ID8gZmllbGQuaGFzVW5pdCA6IG51bGwpXG4gICAgfVxuICB9XG4gIHJldHVybiBmaWVsZFxufVxuXG5leHBvcnQgZnVuY3Rpb24gZmluZEFuZERlY29kZVF1YW50aXR5VmFsdWVGaWVsZHMob2JqOiBhbnkpIHtcbiAgZm9yIChsZXQga2V5IGluIG9iaikge1xuICAgIGlmICh0eXBlb2Ygb2JqW2tleV0gPT09ICdvYmplY3QnICYmIG9ialtrZXldICE9PSBudWxsKSB7XG4gICAgICBpZiAob2JqW2tleV0uaGFzTnVtZXJpY2FsVmFsdWUgIT09IHVuZGVmaW5lZCAmJiBvYmpba2V5XS5oYXNVbml0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgb2JqW2tleV0gPSBkZWNvZGVQb3RlbnRpYWxRdWFudGl0eVZhbHVlRmllbGQob2JqW2tleV0pXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBvYmpcbn1cblxuLy8gY29uc3QgZGF0ZUZpZWxkcyA9IFsnZHVlJywgJ2hhc0JlZ2lubmluZycsICdoYXNFbmQnLCAnaGFzUG9pbnRJblRpbWUnXVxuLy8gZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdERhdGVzKG9iajogYW55KSB7XG4vLyAgIGRhdGVGaWVsZHMuZm9yRWFjaChmaWVsZCA9PiB7XG4vLyAgICAgaWYgKG9ialtmaWVsZF0pIHtcbi8vICAgICAgIG9ialtmaWVsZF0gPSBuZXcgRGF0ZShvYmpbZmllbGRdIC8gMTAwMClcbi8vICAgICB9XG4vLyAgIH0pXG4vLyAgIHJldHVybiBvYmpcbi8vIH1cblxuLy8gZXhwb3J0IGZ1bmN0aW9uIHJldmVyc2VGb3JtYXREYXRlcyhvYmo6IGFueSkge1xuLy8gICBkYXRlRmllbGRzLmZvckVhY2goZmllbGQgPT4ge1xuLy8gICAgIGlmIChvYmpbZmllbGRdKSB7XG4vLyAgICAgICBvYmpbZmllbGRdID0gbmV3IERhdGUob2JqW2ZpZWxkXSkuZ2V0VGltZSgpICogMTAwMFxuLy8gICAgIH1cbi8vICAgfSlcbi8vICAgcmV0dXJuIG9ialxuLy8gfVxuY29uc3QgZGF0ZUZpZWxkcyA9IFsnZHVlJywgJ2hhc0JlZ2lubmluZycsICdoYXNFbmQnLCAnaGFzUG9pbnRJblRpbWUnXVxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdERhdGVzKG9iajogYW55KSB7XG4gIGRhdGVGaWVsZHMuZm9yRWFjaChmaWVsZCA9PiB7XG4gICAgaWYgKG9ialtmaWVsZF0pIHtcbiAgICAgIC8vIE9ubHkgY29udmVydCBpZiBub3QgYWxyZWFkeSBhIERhdGVcbiAgICAgIGlmICghKG9ialtmaWVsZF0gaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICBvYmpbZmllbGRdID0gbmV3IERhdGUob2JqW2ZpZWxkXSAvIDEwMDApXG4gICAgICB9XG4gICAgfVxuICB9KVxuICByZXR1cm4gb2JqXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXZlcnNlRm9ybWF0RGF0ZXMob2JqOiBhbnkpIHtcbiAgZGF0ZUZpZWxkcy5mb3JFYWNoKGZpZWxkID0+IHtcbiAgICBpZiAob2JqW2ZpZWxkXSkge1xuICAgICAgLy8gT25seSBjb252ZXJ0IGlmIG5vdCBhbHJlYWR5IGEgbnVtYmVyICh0aW1lc3RhbXApXG4gICAgICBpZiAob2JqW2ZpZWxkXSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgb2JqW2ZpZWxkXSA9IG9ialtmaWVsZF0uZ2V0VGltZSgpICogMTAwMFxuICAgICAgfVxuICAgIH1cbiAgfSlcbiAgcmV0dXJuIG9ialxufVxuXG5leHBvcnQgZnVuY3Rpb24gcGx1cmFsaXplKHN0cjogc3RyaW5nKSB7XG4gIGlmIChzdHIgPT09ICdwZXJzb24nKSB7XG4gICAgcmV0dXJuICdwZW9wbGUnXG4gIH0gZWxzZSBpZiAoc3RyLmVuZHNXaXRoKCdzJykpIHtcbiAgICByZXR1cm4gc3RyICsgJ2VzJ1xuICB9IGVsc2UgaWYgKHN0ci5lbmRzV2l0aCgneScpKSB7XG4gICAgcmV0dXJuIHN0ci5zbGljZSgwLCAtMSkgKyAnaWVzJ1xuICB9IGVsc2UgaWYgKHN0ci5lbmRzV2l0aCgnbycpKSB7XG4gICAgcmV0dXJuIHN0ciArICdlcydcbiAgfSBlbHNlIGlmIChzdHIuZW5kc1dpdGgoJ2NoJykpIHtcbiAgICByZXR1cm4gc3RyICsgJ2VzJ1xuICB9IGVsc2UgaWYgKHN0ci5lbmRzV2l0aCgnc2gnKSkge1xuICAgIHJldHVybiBzdHIgKyAnZXMnXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHN0ciArICdzJ1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVIYXNoRmllbGRzKG9iajogYW55LCBoYXNoRmllbGRzOiBzdHJpbmdbXSkge1xuICBoYXNoRmllbGRzLmZvckVhY2goZmllbGQgPT4ge1xuICAgIGlmIChvYmpbZmllbGRdKSB7XG4gICAgICBjb25zdCBkZWNvZGVkRmllbGQgPSBkZWNvZGVIYXNoRnJvbUJhc2U2NChvYmpbZmllbGRdKVxuICAgICAgb2JqW2ZpZWxkXSA9IGRlY29kZWRGaWVsZFxuICAgICAgb2JqW2Ake2ZpZWxkfUlkYF0gPSBkZWNvZGVkRmllbGRcbiAgICB9XG4gIH0pXG4gIHJldHVybiBvYmpcbn1cblxuY29uc3QgYWN0aW9ucyA9IHtcbiAgXCJkcm9wb2ZmXCI6IHtcbiAgICBpZDogXCJkcm9wb2ZmXCIsXG4gICAgbGFiZWw6IFwiZHJvcG9mZlwiLFxuICAgIHJlc291cmNlRWZmZWN0OiBcImRlY3JlbWVudFwiLFxuICAgIG9uaGFuZEVmZmVjdDogXCJkZWNyZW1lbnRcIixcbiAgICBpbnB1dE91dHB1dDogXCJvdXRwdXRcIixcbiAgICBwYWlyc1dpdGg6IFwicGlja3VwXCJcbiAgfSxcbiAgXCJwaWNrdXBcIjoge1xuICAgIGlkOiBcInBpY2t1cFwiLFxuICAgIGxhYmVsOiBcInBpY2t1cFwiLFxuICAgIHJlc291cmNlRWZmZWN0OiBcImluY3JlbWVudFwiLFxuICAgIG9uaGFuZEVmZmVjdDogXCJpbmNyZW1lbnRcIixcbiAgICBpbnB1dE91dHB1dDogXCJpbnB1dFwiLFxuICAgIHBhaXJzV2l0aDogXCJkcm9wb2ZmXCJcbiAgfSxcbiAgXCJjb25zdW1lXCI6IHtcbiAgICBpZDogXCJjb25zdW1lXCIsXG4gICAgbGFiZWw6IFwiY29uc3VtZVwiLFxuICAgIHJlc291cmNlRWZmZWN0OiBcImRlY3JlbWVudFwiLFxuICAgIG9uaGFuZEVmZmVjdDogXCJkZWNyZW1lbnRcIixcbiAgICBpbnB1dE91dHB1dDogXCJpbnB1dFwiLFxuICAgIHBhaXJzV2l0aDogXCJub3RBcHBsaWNhYmxlXCJcbiAgfSxcbiAgXCJ1c2VcIjoge1xuICAgIGlkOiBcInVzZVwiLFxuICAgIGxhYmVsOiBcInVzZVwiLFxuICAgIHJlc291cmNlRWZmZWN0OiBcIm5vRWZmZWN0XCIsXG4gICAgb25oYW5kRWZmZWN0OiBcIm5vRWZmZWN0XCIsXG4gICAgaW5wdXRPdXRwdXQ6IFwiaW5wdXRcIixcbiAgICBwYWlyc1dpdGg6IFwibm90QXBwbGljYWJsZVwiXG4gIH0sXG4gIFwid29ya1wiOiB7XG4gICAgaWQ6IFwid29ya1wiLFxuICAgIGxhYmVsOiBcIndvcmtcIixcbiAgICByZXNvdXJjZUVmZmVjdDogXCJub0VmZmVjdFwiLFxuICAgIG9uaGFuZEVmZmVjdDogXCJub0VmZmVjdFwiLFxuICAgIGlucHV0T3V0cHV0OiBcImlucHV0XCIsXG4gICAgcGFpcnNXaXRoOiBcIm5vdEFwcGxpY2FibGVcIlxuICB9LFxuICBcImNpdGVcIjoge1xuICAgIGlkOiBcImNpdGVcIixcbiAgICBsYWJlbDogXCJjaXRlXCIsXG4gICAgcmVzb3VyY2VFZmZlY3Q6IFwibm9FZmZlY3RcIixcbiAgICBvbmhhbmRFZmZlY3Q6IFwibm9FZmZlY3RcIixcbiAgICBpbnB1dE91dHB1dDogXCJpbnB1dFwiLFxuICAgIHBhaXJzV2l0aDogXCJub3RBcHBsaWNhYmxlXCJcbiAgfSxcbiAgXCJwcm9kdWNlXCI6IHtcbiAgICBpZDogXCJwcm9kdWNlXCIsXG4gICAgbGFiZWw6IFwicHJvZHVjZVwiLFxuICAgIHJlc291cmNlRWZmZWN0OiBcImluY3JlbWVudFwiLFxuICAgIG9uaGFuZEVmZmVjdDogXCJpbmNyZW1lbnRcIixcbiAgICBpbnB1dE91dHB1dDogXCJvdXRwdXRcIixcbiAgICBwYWlyc1dpdGg6IFwibm90QXBwbGljYWJsZVwiXG4gIH0sXG4gIFwiYWNjZXB0XCI6IHtcbiAgICBpZDogXCJhY2NlcHRcIixcbiAgICBsYWJlbDogXCJhY2NlcHRcIixcbiAgICByZXNvdXJjZUVmZmVjdDogXCJub0VmZmVjdFwiLFxuICAgIG9uaGFuZEVmZmVjdDogXCJkZWNyZW1lbnRcIixcbiAgICBpbnB1dE91dHB1dDogXCJpbnB1dFwiLFxuICAgIHBhaXJzV2l0aDogXCJtb2RpZnlcIlxuICB9LFxuICBcIm1vZGlmeVwiOiB7XG4gICAgaWQ6IFwibW9kaWZ5XCIsXG4gICAgbGFiZWw6IFwibW9kaWZ5XCIsXG4gICAgcmVzb3VyY2VFZmZlY3Q6IFwibm9FZmZlY3RcIixcbiAgICBvbmhhbmRFZmZlY3Q6IFwiaW5jcmVtZW50XCIsXG4gICAgaW5wdXRPdXRwdXQ6IFwib3V0cHV0XCIsXG4gICAgcGFpcnNXaXRoOiBcImFjY2VwdFwiXG4gIH0sXG4gIFwicGFzc1wiOiB7XG4gICAgaWQ6IFwicGFzc1wiLFxuICAgIGxhYmVsOiBcInBhc3NcIixcbiAgICByZXNvdXJjZUVmZmVjdDogXCJub0VmZmVjdFwiLFxuICAgIG9uaGFuZEVmZmVjdDogXCJub0VmZmVjdFwiLFxuICAgIGlucHV0T3V0cHV0OiBcIm91dHB1dFwiLFxuICAgIHBhaXJzV2l0aDogXCJhY2NlcHRcIlxuICB9LFxuICBcImZhaWxcIjoge1xuICAgIGlkOiBcImZhaWxcIixcbiAgICBsYWJlbDogXCJmYWlsXCIsXG4gICAgcmVzb3VyY2VFZmZlY3Q6IFwibm9FZmZlY3RcIixcbiAgICBvbmhhbmRFZmZlY3Q6IFwibm9FZmZlY3RcIixcbiAgICBpbnB1dE91dHB1dDogXCJvdXRwdXRcIixcbiAgICBwYWlyc1dpdGg6IFwiYWNjZXB0XCJcbiAgfSxcbiAgXCJkZWxpdmVyLXNlcnZpY2VcIjoge1xuICAgIGlkOiBcImRlbGl2ZXItc2VydmljZVwiLFxuICAgIGxhYmVsOiBcImRlbGl2ZXItc2VydmljZVwiLFxuICAgIHJlc291cmNlRWZmZWN0OiBcIm5vRWZmZWN0XCIsXG4gICAgb25oYW5kRWZmZWN0OiBcIm5vRWZmZWN0XCIsXG4gICAgaW5wdXRPdXRwdXQ6IFwib3V0cHV0XCIsXG4gICAgcGFpcnNXaXRoOiBcIm5vdEFwcGxpY2FibGVcIlxuICB9LFxuICBcInRyYW5zZmVyLWFsbC1yaWdodHNcIjoge1xuICAgIGlkOiBcInRyYW5zZmVyLWFsbC1yaWdodHNcIixcbiAgICBsYWJlbDogXCJ0cmFuc2Zlci1hbGwtcmlnaHRzXCIsXG4gICAgcmVzb3VyY2VFZmZlY3Q6IFwiZGVjcmVtZW50SW5jcmVtZW50XCIsXG4gICAgb25oYW5kRWZmZWN0OiBcIm5vRWZmZWN0XCIsXG4gICAgaW5wdXRPdXRwdXQ6IF