#!/usr/bin/env node // coding-tools/figma-tools/js/src/get-design-context.ts import { createHash } from "node:crypto"; // coding-tools/figma-tools/js/src/_utils/cli-args.ts function parseArgs(argv = process.argv.slice(2)) { const args = { _: [] }; for (let i = 0; i < argv.length; i += 1) { const arg = argv[i]; if (!arg.startsWith("-") || arg === "-") { args._.push(arg); continue; } if (arg === "--") { const remaining = argv.slice(i + 1); args._.push(...remaining); break; } const [rawKey, inlineValue] = arg.split("=", 2); const normalisedKey = rawKey.replace(/^-+/, ""); let value; if (inlineValue !== void 0) { value = inlineValue; } else { const next = argv[i + 1]; if (next !== void 0 && !next.startsWith("-")) { value = next; i += 1; } else { value = true; } } args[normalisedKey] = value; } return args; } // coding-tools/figma-tools/js/src/_utils/config.ts var config_default = { schemaVersion: "1.0.0", source: "agentic-coding-templates/figma-tools", http: { maxAttempts: 5, initialDelayMs: 250 } }; // coding-tools/figma-tools/js/src/_utils/envelope.ts function buildRateLimitMeta(rateLimit = {}) { return { remaining: rateLimit.remaining ?? null, resetAt: rateLimit.resetAt ?? null, attempts: rateLimit.attempts ?? 1, lastWaitMs: rateLimit.lastWaitMs ?? 0 }; } function createEnvelope({ tool, input = {}, data = {}, warnings = [], errors = [], rateLimit, schemaVersion }) { return { schemaVersion: schemaVersion ?? config_default.schemaVersion, tool, input, meta: { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), source: config_default.source, rateLimit: buildRateLimitMeta(rateLimit) }, data, warnings, errors }; } // coding-tools/figma-tools/js/src/_utils/errors.ts var ERROR_EXIT_CODES = { INPUT_INVALID: 1, CONFIG_INVALID: 1, FIGMA_AUTH: 1, FIGMA_NOT_FOUND: 2, FIGMA_RATE_LIMIT: 2, NETWORK: 2, INTERNAL: 3 }; function createError(code, message, detail) { return { code, message, detail: detail ?? null }; } function getExitCode(errors = []) { if (!errors.length) { return 0; } return errors.reduce((max, error) => { const exitCode = ERROR_EXIT_CODES[error.code] ?? 1; return Math.max(max, exitCode); }, 0); } // coding-tools/figma-tools/js/src/_utils/http-client.ts var BASE_URL = "https://api.figma.com"; function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } function parseJsonSafely(text) { try { return text ? JSON.parse(text) : {}; } catch { return { raw: text }; } } function parseRateLimit(headers, attempts, lastWaitMs) { const remainingHeader = headers.get("x-ratelimit-remaining"); const resetHeader = headers.get("x-ratelimit-reset"); let remaining = null; if (remainingHeader !== null && remainingHeader !== void 0) { const parsed = Number(remainingHeader); remaining = Number.isNaN(parsed) ? null : parsed; } let resetAt = null; if (resetHeader) { const numericReset = Number(resetHeader); if (!Number.isNaN(numericReset)) { resetAt = new Date(numericReset * 1e3).toISOString(); } else { const date = new Date(resetHeader); if (!Number.isNaN(date.valueOf())) { resetAt = date.toISOString(); } } } return { remaining, resetAt, attempts, lastWaitMs }; } function computeBackoffMs(attempt, initialDelayMs) { return initialDelayMs * 2 ** (attempt - 1); } async function figmaRequest(options) { const { path, method = "GET", token, headers = {}, body, searchParams, maxAttempts = config_default.http?.maxAttempts ?? 5, initialDelayMs = config_default.http?.initialDelayMs ?? 250 } = options; if (!token) { return { ok: false, error: createError("FIGMA_AUTH", "FIGMA_ACCESS_TOKEN is missing from the environment."), status: null, rateLimit: null }; } const url = new URL(path, BASE_URL); if (searchParams) { Object.entries(searchParams).forEach(([key, value]) => { if (value === void 0 || value === null) return; url.searchParams.append(key, String(value)); }); } let attempt = 0; let lastWaitMs = 0; while (attempt < maxAttempts) { attempt += 1; const response = await fetch(url, { method, headers: { "Content-Type": "application/json", "X-Figma-Token": token, ...headers }, body: body ? JSON.stringify(body) : void 0 }); const text = await response.text(); const payload = parseJsonSafely(text); const rateLimit = parseRateLimit(response.headers, attempt, lastWaitMs); if (response.ok) { return { ok: true, data: payload, rateLimit }; } const status = response.status; if (status === 401 || status === 403) { return { ok: false, error: createError("FIGMA_AUTH", payload?.message ?? "Figma token is unauthorized.", { status }), status, rateLimit }; } if (status === 404) { return { ok: false, error: createError("FIGMA_NOT_FOUND", payload?.message ?? "Resource not found.", { status }), status, rateLimit }; } if (status === 429 || status >= 500) { if (attempt >= maxAttempts) { return { ok: false, error: createError(status === 429 ? "FIGMA_RATE_LIMIT" : "NETWORK", payload?.message ?? "Figma request failed after maximum retries.", { status }), status, rateLimit }; } let waitMs = computeBackoffMs(attempt, initialDelayMs); const resetHeader = response.headers.get("x-ratelimit-reset"); if (resetHeader) { const asNumber = Number(resetHeader); if (!Number.isNaN(asNumber)) { const resetMs = asNumber * 1e3; const delta = resetMs - Date.now(); if (delta > 0) waitMs = Math.max(waitMs, delta); } } const jitter = Math.floor(Math.random() * 100); lastWaitMs = waitMs + jitter; await sleep(lastWaitMs); continue; } return { ok: false, error: createError("INTERNAL", payload?.message ?? "Unexpected error from Figma API.", { status }), status, rateLimit }; } return { ok: false, error: createError("NETWORK", "Unable to reach Figma API."), status: null, rateLimit: { remaining: null, resetAt: null, attempts: maxAttempts, lastWaitMs } }; } // coding-tools/figma-tools/js/src/_utils/url-parse.ts var FILE_KEY_REGEX = /figma\.com\/(?:file|design)\/([A-Za-z0-9]+)\//i; function parseFigmaUrl(input) { if (!input) return { fileKey: null, nodeId: null }; try { const url = new URL(input); const match = url.href.match(FILE_KEY_REGEX); const fileKey = match ? match[1] : null; const nodeParam = url.searchParams.get("node-id"); const nodeId = nodeParam ? ensureNodeId(nodeParam) : null; return { fileKey, nodeId }; } catch { return { fileKey: null, nodeId: null }; } } function ensureNodeId(value) { if (!value) return null; const decoded = decodeURIComponent(value); if (decoded.includes(":")) return decoded; if (/^[0-9]+-[0-9]+$/.test(decoded)) { const [left, right] = decoded.split("-", 2); return `${left}:${right}`; } return decoded; } // coding-tools/figma-tools/js/src/get-design-context.ts var TOOL_NAME = "get-design-context"; var VALID_IMAGE_FORMATS = ["png", "jpg", "jpeg", "svg"]; function log(message, verbose) { if (verbose) { process.stderr.write(`[${TOOL_NAME}] ${message} `); } } function toOptionalString(value) { return typeof value === "string" && value.length > 0 ? value : null; } function exitWithEnvelope(envelope, errors = []) { process.stdout.write(`${JSON.stringify(envelope, null, 2)} `); process.exit(getExitCode(errors)); } function mapLayoutNode(node) { const children = Array.isArray(node.children) ? node.children.map(mapLayoutNode) : []; const bbox = node.absoluteBoundingBox; const layout = bbox ? { x: bbox.x ?? 0, y: bbox.y ?? 0, width: bbox.width ?? 0, height: bbox.height ?? 0 } : null; return { id: node.id, name: node.name, type: node.type, visible: node.visible ?? true, layout, rotation: node.rotation ?? 0, clipsContent: node.clipsContent ?? false, characters: node.characters ?? null, fills: node.fills ?? [], strokes: node.strokes ?? [], effects: node.effects ?? [], tailwindSuggestion: null, children }; } function buildStyleTokens(node) { const cornerRadius = Array.isArray(node.rectangleCornerRadii) && node.rectangleCornerRadii.length > 0 ? node.rectangleCornerRadii : node.cornerRadius ?? null; return { fills: node.fills ?? [], strokes: node.strokes ?? [], effects: node.effects ?? [], backgroundColor: node.backgroundColor ?? null, textStyle: node.style ?? null, styles: node.styles ?? {}, cornerRadius }; } function buildSelectionSummary(node, components, componentSets) { const componentId = node.componentId ?? null; const componentSetId = node.componentSetId ?? null; const componentMeta = componentId ? components[componentId] ?? null : null; const componentSetMeta = componentSetId ? componentSets[componentSetId] ?? null : null; return { id: node.id, name: node.name, type: node.type, componentId, componentKey: componentMeta?.key ?? null, componentName: componentMeta?.name ?? null, componentSetId, componentSetName: componentSetMeta?.name ?? null, variantProperties: node.variantProperties ?? null }; } function computeLayoutHash(layoutTree) { const json = JSON.stringify(layoutTree); return createHash("sha1").update(json).digest("hex"); } async function fetchPreviewImage(fileKey, nodeId, token, imageFormat, scale, warnings, verbose) { const format = VALID_IMAGE_FORMATS.includes(imageFormat) ? imageFormat : "png"; const scaleClamped = Number.isFinite(scale) && scale > 0 ? scale : 1; log(`Requesting preview image format=${format}, scale=${scaleClamped}`, verbose); const imageResponse = await figmaRequest({ path: `/v1/images/${fileKey}`, token, searchParams: { ids: nodeId, format, scale: scaleClamped } }); if (!imageResponse.ok) { warnings.push(imageResponse.error?.message ?? "Failed to request preview image."); return null; } const url = imageResponse.data?.images?.[nodeId]; if (!url) return null; return { url, format, size: `${scaleClamped}x` }; } async function main() { const args = parseArgs(); const verbose = Boolean(args.verbose ?? args.v); const schemaVersion = toOptionalString(args["schema-version"]) ?? void 0; const warnings = []; const errors = []; const token = process.env.FIGMA_ACCESS_TOKEN; if (!token || !token.trim()) { errors.push(createError("FIGMA_AUTH", "FIGMA_ACCESS_TOKEN is required but was not provided.")); const envelope2 = createEnvelope({ tool: TOOL_NAME, input: { fileKey: null, nodeId: null, includeImages: false, imageFormat: "png", scale: 1 }, warnings, errors, schemaVersion, data: {} }); exitWithEnvelope(envelope2, errors); } const urlInput = toOptionalString(args.url) ?? toOptionalString(args.u); let fileKey = toOptionalString(args["file-key"]) ?? void 0; let nodeId = ensureNodeId(toOptionalString(args["node-id"])); if (urlInput) { const parsed = parseFigmaUrl(urlInput); fileKey = fileKey || parsed.fileKey || void 0; nodeId = nodeId || parsed.nodeId; } const includeImages = args["include-images"] !== "false"; const imageFormatInput = String(args["image-format"] ?? "png").toLowerCase(); const imageFormat = VALID_IMAGE_FORMATS.includes(imageFormatInput) ? imageFormatInput : "png"; const scaleInput = Number(args.scale ?? 1); const imageScale = Number.isFinite(scaleInput) && scaleInput > 0 ? scaleInput : 1; const input = { fileKey: fileKey ?? null, nodeId: nodeId ?? null, includeImages, imageFormat, scale: imageScale }; if (!fileKey) { errors.push(createError("INPUT_INVALID", "A valid Figma file key is required (--file-key or --url).")); } if (!nodeId) { errors.push(createError("INPUT_INVALID", "A valid Figma node id is required (--node-id or --url with node-id).")); } if (errors.length) { const envelope2 = createEnvelope({ tool: TOOL_NAME, input, warnings, errors, data: {}, schemaVersion }); exitWithEnvelope(envelope2, errors); } const resolvedFileKey = fileKey; const resolvedNodeId = nodeId; log(`Fetching node ${resolvedNodeId} from file ${resolvedFileKey}`, verbose); const nodeResponse = await figmaRequest({ path: `/v1/files/${resolvedFileKey}/nodes`, token, searchParams: { ids: resolvedNodeId } }); if (!nodeResponse.ok) { errors.push(nodeResponse.error ?? createError("INTERNAL", "Failed to fetch node data.")); const envelope2 = createEnvelope({ tool: TOOL_NAME, input, warnings, errors, rateLimit: nodeResponse.rateLimit ?? void 0, data: {}, schemaVersion }); exitWithEnvelope(envelope2, errors); } const nodePayload = nodeResponse.data ?? {}; const nodesMap = nodePayload.nodes ?? {}; const nodeWrapper = nodesMap[resolvedNodeId]; if (!nodeWrapper || !nodeWrapper.document) { errors.push(createError("FIGMA_NOT_FOUND", `Node ${resolvedNodeId} was not found in file ${resolvedFileKey}.`)); const envelope2 = createEnvelope({ tool: TOOL_NAME, input, warnings, errors, rateLimit: nodeResponse.rateLimit ?? void 0, data: {}, schemaVersion }); exitWithEnvelope(envelope2, errors); } const node = nodeWrapper.document; const components = nodeWrapper.components ?? {}; const componentSets = nodeWrapper.componentSets ?? {}; const selectionSummary = buildSelectionSummary(node, components, componentSets); const layoutTree = mapLayoutNode(node); const styleTokens = buildStyleTokens(node); const layoutHash = computeLayoutHash(layoutTree); let preview = null; if (includeImages) { preview = await fetchPreviewImage( resolvedFileKey, resolvedNodeId, token, imageFormat, imageScale, warnings, verbose ); } const data = { file: { key: resolvedFileKey, name: nodePayload?.name ?? null, lastModified: nodePayload?.lastModified ?? null }, selectionSummary, layoutTree, styleTokens, layoutHash, images: preview ? { preview } : null }; const envelope = createEnvelope({ tool: TOOL_NAME, input, data, warnings, errors, rateLimit: nodeResponse.rateLimit ?? void 0, schemaVersion }); process.stdout.write(`${JSON.stringify(envelope, null, 2)} `); process.exit(getExitCode(errors)); } main().catch((error) => { const message = error instanceof Error ? error.message : "Unknown error"; const envelope = createEnvelope({ tool: TOOL_NAME, input: { fileKey: null, nodeId: null, includeImages: false, imageFormat: "png", scale: 1 }, errors: [createError("INTERNAL", message, { stack: error instanceof Error ? error.stack : void 0 })], data: {} }); process.stdout.write(`${JSON.stringify(envelope, null, 2)} `); process.exit(3); }); //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2dldC1kZXNpZ24tY29udGV4dC50cyIsICIuLi9zcmMvX3V0aWxzL2NsaS1hcmdzLnRzIiwgIi4uL3NyYy9fdXRpbHMvY29uZmlnLnRzIiwgIi4uL3NyYy9fdXRpbHMvZW52ZWxvcGUudHMiLCAiLi4vc3JjL191dGlscy9lcnJvcnMudHMiLCAiLi4vc3JjL191dGlscy9odHRwLWNsaWVudC50cyIsICIuLi9zcmMvX3V0aWxzL3VybC1wYXJzZS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiIyEvdXNyL2Jpbi9lbnYgbm9kZVxuXG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnbm9kZTpjcnlwdG8nXG5pbXBvcnQgeyBwYXJzZUFyZ3MsIHR5cGUgQ2xpQXJncyB9IGZyb20gJy4vX3V0aWxzL2NsaS1hcmdzLnRzJ1xuaW1wb3J0IHsgY3JlYXRlRW52ZWxvcGUsIHR5cGUgVG9vbEVudmVsb3BlIH0gZnJvbSAnLi9fdXRpbHMvZW52ZWxvcGUudHMnXG5pbXBvcnQgeyBjcmVhdGVFcnJvciwgZ2V0RXhpdENvZGUsIHR5cGUgVG9vbEVycm9yIH0gZnJvbSAnLi9fdXRpbHMvZXJyb3JzLnRzJ1xuaW1wb3J0IHsgZmlnbWFSZXF1ZXN0IH0gZnJvbSAnLi9fdXRpbHMvaHR0cC1jbGllbnQudHMnXG5pbXBvcnQgeyBwYXJzZUZpZ21hVXJsLCBlbnN1cmVOb2RlSWQgfSBmcm9tICcuL191dGlscy91cmwtcGFyc2UudHMnXG5cbmNvbnN0IFRPT0xfTkFNRSA9ICdnZXQtZGVzaWduLWNvbnRleHQnXG5jb25zdCBWQUxJRF9JTUFHRV9GT1JNQVRTID0gWydwbmcnLCAnanBnJywgJ2pwZWcnLCAnc3ZnJ11cblxudHlwZSBFbXB0eURhdGEgPSBSZWNvcmQ8c3RyaW5nLCBuZXZlcj5cblxuaW50ZXJmYWNlIFRvb2xJbnB1dCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgZmlsZUtleTogc3RyaW5nIHwgbnVsbFxuICBub2RlSWQ6IHN0cmluZyB8IG51bGxcbiAgaW5jbHVkZUltYWdlczogYm9vbGVhblxuICBpbWFnZUZvcm1hdDogc3RyaW5nXG4gIHNjYWxlOiBudW1iZXJcbn1cblxuaW50ZXJmYWNlIERlc2lnbkNvbnRleHREYXRhIHtcbiAgZmlsZToge1xuICAgIGtleTogc3RyaW5nXG4gICAgbmFtZTogc3RyaW5nIHwgbnVsbFxuICAgIGxhc3RNb2RpZmllZDogc3RyaW5nIHwgbnVsbFxuICB9XG4gIHNlbGVjdGlvblN1bW1hcnk6IFNlbGVjdGlvblN1bW1hcnlcbiAgbGF5b3V0VHJlZTogTGF5b3V0Tm9kZVxuICBzdHlsZVRva2VuczogU3R5bGVUb2tlbnNcbiAgbGF5b3V0SGFzaDogc3RyaW5nIHwgbnVsbFxuICBpbWFnZXM6IHsgcHJldmlldzogUHJldmlld0ltYWdlIH0gfCBudWxsXG59XG5cbmludGVyZmFjZSBGaWdtYUNvbXBvbmVudE1ldGEge1xuICBrZXk/OiBzdHJpbmdcbiAgbmFtZT86IHN0cmluZ1xuICBkZXNjcmlwdGlvbj86IHN0cmluZ1xufVxuXG5pbnRlcmZhY2UgRmlnbWFDb21wb25lbnRTZXRNZXRhIHtcbiAgbmFtZT86IHN0cmluZ1xuICBjb21wb25lbnRTZXRQcm9wZXJ0aWVzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbn1cblxuaW50ZXJmYWNlIEZpZ21hTm9kZSB7XG4gIGlkOiBzdHJpbmdcbiAgbmFtZT86IHN0cmluZ1xuICB0eXBlPzogc3RyaW5nXG4gIGNvbXBvbmVudElkPzogc3RyaW5nXG4gIGNvbXBvbmVudFNldElkPzogc3RyaW5nXG4gIHZhcmlhbnRQcm9wZXJ0aWVzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgYWJzb2x1dGVCb3VuZGluZ0JveD86IHsgeD86IG51bWJlcjsgeT86IG51bWJlcjsgd2lkdGg/OiBudW1iZXI7IGhlaWdodD86IG51bWJlciB9XG4gIGNoaWxkcmVuPzogRmlnbWFOb2RlW11cbiAgdmlzaWJsZT86IGJvb2xlYW5cbiAgcm90YXRpb24/OiBudW1iZXJcbiAgY2xpcHNDb250ZW50PzogYm9vbGVhblxuICBjaGFyYWN0ZXJzPzogc3RyaW5nXG4gIGZpbGxzPzogdW5rbm93bltdXG4gIHN0cm9rZXM/OiB1bmtub3duW11cbiAgZWZmZWN0cz86IHVua25vd25bXVxuICBzdHlsZT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4gIHN0eWxlcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4gIGJhY2tncm91bmRDb2xvcj86IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4gIGNvcm5lclJhZGl1cz86IG51bWJlclxuICByZWN0YW5nbGVDb3JuZXJSYWRpaT86IG51bWJlcltdXG59XG5cbmludGVyZmFjZSBOb2RlV3JhcHBlciB7XG4gIGRvY3VtZW50PzogRmlnbWFOb2RlXG4gIGNvbXBvbmVudHM/OiBSZWNvcmQ8c3RyaW5nLCBGaWdtYUNvbXBvbmVudE1ldGE+XG4gIGNvbXBvbmVudFNldHM/OiBSZWNvcmQ8c3RyaW5nLCBGaWdtYUNvbXBvbmVudFNldE1ldGE+XG59XG5cbmludGVyZmFjZSBOb2Rlc1Jlc3BvbnNlIHtcbiAgbmFtZT86IHN0cmluZ1xuICBsYXN0TW9kaWZpZWQ/OiBzdHJpbmdcbiAgbm9kZXM/OiBSZWNvcmQ8c3RyaW5nLCBOb2RlV3JhcHBlcj5cbn1cblxuaW50ZXJmYWNlIEltYWdlUmVzcG9uc2Uge1xuICBpbWFnZXM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+XG59XG5cbmludGVyZmFjZSBTZWxlY3Rpb25TdW1tYXJ5IHtcbiAgaWQ6IHN0cmluZ1xuICBuYW1lPzogc3RyaW5nXG4gIHR5cGU/OiBzdHJpbmdcbiAgY29tcG9uZW50SWQ/OiBzdHJpbmcgfCBudWxsXG4gIGNvbXBvbmVudEtleT86IHN0cmluZyB8IG51bGxcbiAgY29tcG9uZW50TmFtZT86IHN0cmluZyB8IG51bGxcbiAgY29tcG9uZW50U2V0SWQ/OiBzdHJpbmcgfCBudWxsXG4gIGNvbXBvbmVudFNldE5hbWU/OiBzdHJpbmcgfCBudWxsXG4gIHZhcmlhbnRQcm9wZXJ0aWVzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCBudWxsXG59XG5cbmludGVyZmFjZSBMYXlvdXROb2RlIHtcbiAgaWQ6IHN0cmluZ1xuICBuYW1lPzogc3RyaW5nXG4gIHR5cGU/OiBzdHJpbmdcbiAgdmlzaWJsZTogYm9vbGVhblxuICBsYXlvdXQ6IHsgeDogbnVtYmVyOyB5OiBudW1iZXI7IHdpZHRoOiBudW1iZXI7IGhlaWdodDogbnVtYmVyIH0gfCBudWxsXG4gIHJvdGF0aW9uOiBudW1iZXJcbiAgY2xpcHNDb250ZW50OiBib29sZWFuXG4gIGNoYXJhY3RlcnM6IHN0cmluZyB8IG51bGxcbiAgZmlsbHM6IHVua25vd25bXVxuICBzdHJva2VzOiB1bmtub3duW11cbiAgZWZmZWN0czogdW5rbm93bltdXG4gIHRhaWx3aW5kU3VnZ2VzdGlvbjogbnVsbFxuICBjaGlsZHJlbjogTGF5b3V0Tm9kZVtdXG59XG5cbmludGVyZmFjZSBTdHlsZVRva2VucyB7XG4gIGZpbGxzOiB1bmtub3duW11cbiAgc3Ryb2tlczogdW5rbm93bltdXG4gIGVmZmVjdHM6IHVua25vd25bXVxuICBiYWNrZ3JvdW5kQ29sb3I6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgbnVsbFxuICB0ZXh0U3R5bGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgbnVsbFxuICBzdHlsZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4gIGNvcm5lclJhZGl1czogbnVtYmVyIHwgbnVtYmVyW10gfCBudWxsXG59XG5cbmludGVyZmFjZSBQcmV2aWV3SW1hZ2Uge1xuICB1cmw6IHN0cmluZ1xuICBmb3JtYXQ6IHN0cmluZ1xuICBzaXplOiBzdHJpbmdcbn1cblxuZnVuY3Rpb24gbG9nKG1lc3NhZ2U6IHN0cmluZywgdmVyYm9zZTogYm9vbGVhbik6IHZvaWQge1xuICBpZiAodmVyYm9zZSkge1xuICAgIHByb2Nlc3Muc3RkZXJyLndyaXRlKGBbJHtUT09MX05BTUV9XSAke21lc3NhZ2V9XFxuYClcbiAgfVxufVxuXG5mdW5jdGlvbiB0b09wdGlvbmFsU3RyaW5nKHZhbHVlOiBDbGlBcmdzW3N0cmluZ10pOiBzdHJpbmcgfCBudWxsIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUubGVuZ3RoID4gMCA/IHZhbHVlIDogbnVsbFxufVxuXG5mdW5jdGlvbiBleGl0V2l0aEVudmVsb3BlKFxuICBlbnZlbG9wZTogVG9vbEVudmVsb3BlPFRvb2xJbnB1dCwgRGVzaWduQ29udGV4dERhdGEgfCBFbXB0eURhdGE+LFxuICBlcnJvcnM6IFRvb2xFcnJvcltdID0gW11cbik6IG5ldmVyIHtcbiAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoYCR7SlNPTi5zdHJpbmdpZnkoZW52ZWxvcGUsIG51bGwsIDIpfVxcbmApXG4gIHByb2Nlc3MuZXhpdChnZXRFeGl0Q29kZShlcnJvcnMpKVxufVxuXG5mdW5jdGlvbiBtYXBMYXlvdXROb2RlKG5vZGU6IEZpZ21hTm9kZSk6IExheW91dE5vZGUge1xuICBjb25zdCBjaGlsZHJlbiA9IEFycmF5LmlzQXJyYXkobm9kZS5jaGlsZHJlbikgPyBub2RlLmNoaWxkcmVuLm1hcChtYXBMYXlvdXROb2RlKSA6IFtdXG4gIGNvbnN0IGJib3ggPSBub2RlLmFic29sdXRlQm91bmRpbmdCb3hcbiAgY29uc3QgbGF5b3V0ID0gYmJveFxuICAgID8geyB4OiBiYm94LnggPz8gMCwgeTogYmJveC55ID8/IDAsIHdpZHRoOiBiYm94LndpZHRoID8/IDAsIGhlaWdodDogYmJveC5oZWlnaHQgPz8gMCB9XG4gICAgOiBudWxsXG5cbiAgcmV0dXJuIHtcbiAgICBpZDogbm9kZS5pZCxcbiAgICBuYW1lOiBub2RlLm5hbWUsXG4gICAgdHlwZTogbm9kZS50eXBlLFxuICAgIHZpc2libGU6IG5vZGUudmlzaWJsZSA/PyB0cnVlLFxuICAgIGxheW91dCxcbiAgICByb3RhdGlvbjogbm9kZS5yb3RhdGlvbiA/PyAwLFxuICAgIGNsaXBzQ29udGVudDogbm9kZS5jbGlwc0NvbnRlbnQgPz8gZmFsc2UsXG4gICAgY2hhcmFjdGVyczogbm9kZS5jaGFyYWN0ZXJzID8/IG51bGwsXG4gICAgZmlsbHM6IG5vZGUuZmlsbHMgPz8gW10sXG4gICAgc3Ryb2tlczogbm9kZS5zdHJva2VzID8/IFtdLFxuICAgIGVmZmVjdHM6IG5vZGUuZWZmZWN0cyA/PyBbXSxcbiAgICB0YWlsd2luZFN1Z2dlc3Rpb246IG51bGwsXG4gICAgY2hpbGRyZW4sXG4gIH1cbn1cblxuZnVuY3Rpb24gYnVpbGRTdHlsZVRva2Vucyhub2RlOiBGaWdtYU5vZGUpOiBTdHlsZVRva2VucyB7XG4gIGNvbnN0IGNvcm5lclJhZGl1czogbnVtYmVyIHwgbnVtYmVyW10gfCBudWxsID1cbiAgICAoQXJyYXkuaXNBcnJheShub2RlLnJlY3RhbmdsZUNvcm5lclJhZGlpKSAmJiBub2RlLnJlY3RhbmdsZUNvcm5lclJhZGlpLmxlbmd0aCA+IDApXG4gICAgICA/IG5vZGUucmVjdGFuZ2xlQ29ybmVyUmFkaWlcbiAgICAgIDogKG5vZGUuY29ybmVyUmFkaXVzID8/IG51bGwpXG5cbiAgcmV0dXJuIHtcbiAgICBmaWxsczogbm9kZS5maWxscyA/PyBbXSxcbiAgICBzdHJva2VzOiBub2RlLnN0cm9rZXMgPz8gW10sXG4gICAgZWZmZWN0czogbm9kZS5lZmZlY3RzID8/IFtdLFxuICAgIGJhY2tncm91bmRDb2xvcjogbm9kZS5iYWNrZ3JvdW5kQ29sb3IgPz8gbnVsbCxcbiAgICB0ZXh0U3R5bGU6IG5vZGUuc3R5bGUgPz8gbnVsbCxcbiAgICBzdHlsZXM6IG5vZGUuc3R5bGVzID8/IHt9LFxuICAgIGNvcm5lclJhZGl1cyxcbiAgfVxufVxuXG5mdW5jdGlvbiBidWlsZFNlbGVjdGlvblN1bW1hcnkoXG4gIG5vZGU6IEZpZ21hTm9kZSxcbiAgY29tcG9uZW50czogUmVjb3JkPHN0cmluZywgRmlnbWFDb21wb25lbnRNZXRhPixcbiAgY29tcG9uZW50U2V0czogUmVjb3JkPHN0cmluZywgRmlnbWFDb21wb25lbnRTZXRNZXRhPlxuKTogU2VsZWN0aW9uU3VtbWFyeSB7XG4gIGNvbnN0IGNvbXBvbmVudElkID0gbm9kZS5jb21wb25lbnRJZCA/PyBudWxsXG4gIGNvbnN0IGNvbXBvbmVudFNldElkID0gbm9kZS5jb21wb25lbnRTZXRJZCA/PyBudWxsXG4gIGNvbnN0IGNvbXBvbmVudE1ldGEgPSBjb21wb25lbnRJZCA/IGNvbXBvbmVudHNbY29tcG9uZW50SWRdID8/IG51bGwgOiBudWxsXG4gIGNvbnN0IGNvbXBvbmVudFNldE1ldGEgPSBjb21wb25lbnRTZXRJZCA/IGNvbXBvbmVudFNldHNbY29tcG9uZW50U2V0SWRdID8/IG51bGwgOiBudWxsXG5cbiAgcmV0dXJuIHtcbiAgICBpZDogbm9kZS5pZCxcbiAgICBuYW1lOiBub2RlLm5hbWUsXG4gICAgdHlwZTogbm9kZS50eXBlLFxuICAgIGNvbXBvbmVudElkLFxuICAgIGNvbXBvbmVudEtleTogY29tcG9uZW50TWV0YT8ua2V5ID8/IG51bGwsXG4gICAgY29tcG9uZW50TmFtZTogY29tcG9uZW50TWV0YT8ubmFtZSA/PyBudWxsLFxuICAgIGNvbXBvbmVudFNldElkLFxuICAgIGNvbXBvbmVudFNldE5hbWU6IGNvbXBvbmVudFNldE1ldGE/Lm5hbWUgPz8gbnVsbCxcbiAgICB2YXJpYW50UHJvcGVydGllczogbm9kZS52YXJpYW50UHJvcGVydGllcyA/PyBudWxsLFxuICB9XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVMYXlvdXRIYXNoKGxheW91dFRyZWU6IExheW91dE5vZGUpOiBzdHJpbmcge1xuICBjb25zdCBqc29uID0gSlNPTi5zdHJpbmdpZnkobGF5b3V0VHJlZSlcbiAgcmV0dXJuIGNyZWF0ZUhhc2goJ3NoYTEnKS51cGRhdGUoanNvbikuZGlnZXN0KCdoZXgnKVxufVxuXG5hc3luYyBmdW5jdGlvbiBmZXRjaFByZXZpZXdJbWFnZShcbiAgZmlsZUtleTogc3RyaW5nLFxuICBub2RlSWQ6IHN0cmluZyxcbiAgdG9rZW46IHN0cmluZyxcbiAgaW1hZ2VGb3JtYXQ6IHN0cmluZyxcbiAgc2NhbGU6IG51bWJlcixcbiAgd2FybmluZ3M6IHN0cmluZ1tdLFxuICB2ZXJib3NlOiBib29sZWFuXG4pOiBQcm9taXNlPFByZXZpZXdJbWFnZSB8IG51bGw+IHtcbiAgY29uc3QgZm9ybWF0ID0gVkFMSURfSU1BR0VfRk9STUFUUy5pbmNsdWRlcyhpbWFnZUZvcm1hdCkgPyBpbWFnZUZvcm1hdCA6ICdwbmcnXG4gIGNvbnN0IHNjYWxlQ2xhbXBlZCA9IE51bWJlci5pc0Zpbml0ZShzY2FsZSkgJiYgc2NhbGUgPiAwID8gc2NhbGUgOiAxXG5cbiAgbG9nKGBSZXF1ZXN0aW5nIHByZXZpZXcgaW1hZ2UgZm9ybWF0PSR7Zm9ybWF0fSwgc2NhbGU9JHtzY2FsZUNsYW1wZWR9YCwgdmVyYm9zZSlcbiAgY29uc3QgaW1hZ2VSZXNwb25zZSA9IGF3YWl0IGZpZ21hUmVxdWVzdDxJbWFnZVJlc3BvbnNlPih7XG4gICAgcGF0aDogYC92MS9pbWFnZXMvJHtmaWxlS2V5fWAsXG4gICAgdG9rZW4sXG4gICAgc2VhcmNoUGFyYW1zOiB7IGlkczogbm9kZUlkLCBmb3JtYXQsIHNjYWxlOiBzY2FsZUNsYW1wZWQgfSxcbiAgfSlcblxuICBpZiAoIWltYWdlUmVzcG9uc2Uub2spIHtcbiAgICB3YXJuaW5ncy5wdXNoKGltYWdlUmVzcG9uc2UuZXJyb3I/Lm1lc3NhZ2UgPz8gJ0ZhaWxlZCB0byByZXF1ZXN0IHByZXZpZXcgaW1hZ2UuJylcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgY29uc3QgdXJsID0gaW1hZ2VSZXNwb25zZS5kYXRhPy5pbWFnZXM/Lltub2RlSWRdXG4gIGlmICghdXJsKSByZXR1cm4gbnVsbFxuICByZXR1cm4geyB1cmwsIGZvcm1hdCwgc2l6ZTogYCR7c2NhbGVDbGFtcGVkfXhgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gbWFpbigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgYXJncyA9IHBhcnNlQXJncygpXG4gIGNvbnN0IHZlcmJvc2UgPSBCb29sZWFuKGFyZ3MudmVyYm9zZSA/PyBhcmdzLnYpXG4gIGNvbnN0IHNjaGVtYVZlcnNpb24gPSB0b09wdGlvbmFsU3RyaW5nKGFyZ3NbJ3NjaGVtYS12ZXJzaW9uJ10pID8/IHVuZGVmaW5lZFxuXG4gIGNvbnN0IHdhcm5pbmdzOiBzdHJpbmdbXSA9IFtdXG4gIGNvbnN0IGVycm9yczogVG9vbEVycm9yW10gPSBbXVxuXG4gIGNvbnN0IHRva2VuID0gcHJvY2Vzcy5lbnYuRklHTUFfQUNDRVNTX1RPS0VOXG4gIGlmICghdG9rZW4gfHwgIXRva2VuLnRyaW0oKSkge1xuICAgIGVycm9ycy5wdXNoKGNyZWF0ZUVycm9yKCdGSUdNQV9BVVRIJywgJ0ZJR01BX0FDQ0VTU19UT0tFTiBpcyByZXF1aXJlZCBidXQgd2FzIG5vdCBwcm92aWRlZC4nKSlcbiAgICBjb25zdCBlbnZlbG9wZSA9IGNyZWF0ZUVudmVsb3BlPFRvb2xJbnB1dCwgRW1wdHlEYXRhPih7XG4gICAgICB0b29sOiBUT09MX05BTUUsXG4gICAgICBpbnB1dDogeyBmaWxlS2V5OiBudWxsLCBub2RlSWQ6IG51bGwsIGluY2x1ZGVJbWFnZXM6IGZhbHNlLCBpbWFnZUZvcm1hdDogJ3BuZycsIHNjYWxlOiAxIH0sXG4gICAgICB3YXJuaW5ncyxcbiAgICAgIGVycm9ycyxcbiAgICAgIHNjaGVtYVZlcnNpb24sXG4gICAgICBkYXRhOiB7fSBhcyBFbXB0eURhdGEsXG4gICAgfSlcbiAgICBleGl0V2l0aEVudmVsb3BlKGVudmVsb3BlLCBlcnJvcnMpXG4gIH1cblxuICBjb25zdCB1cmxJbnB1dCA9IHRvT3B0aW9uYWxTdHJpbmcoYXJncy51cmwpID8/IHRvT3B0aW9uYWxTdHJpbmcoYXJncy51KVxuICBsZXQgZmlsZUtleSA9IHRvT3B0aW9uYWxTdHJpbmcoYXJnc1snZmlsZS1rZXknXSkgPz8gdW5kZWZpbmVkXG4gIGxldCBub2RlSWQgPSBlbnN1cmVOb2RlSWQodG9PcHRpb25hbFN0cmluZyhhcmdzWydub2RlLWlkJ10pKVxuXG4gIGlmICh1cmxJbnB1dCkge1xuICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlRmlnbWFVcmwodXJsSW5wdXQpXG4gICAgZmlsZUtleSA9IGZpbGVLZXkgfHwgcGFyc2VkLmZpbGVLZXkgfHwgdW5kZWZpbmVkXG4gICAgbm9kZUlkID0gbm9kZUlkIHx8IHBhcnNlZC5ub2RlSWRcbiAgfVxuXG4gIGNvbnN0IGluY2x1ZGVJbWFnZXMgPSBhcmdzWydpbmNsdWRlLWltYWdlcyddICE9PSAnZmFsc2UnXG4gIGNvbnN0IGltYWdlRm9ybWF0SW5wdXQgPSBTdHJpbmcoYXJnc1snaW1hZ2UtZm9ybWF0J10gPz8gJ3BuZycpLnRvTG93ZXJDYXNlKClcbiAgY29uc3QgaW1hZ2VGb3JtYXQgPSBWQUxJRF9JTUFHRV9GT1JNQVRTLmluY2x1ZGVzKGltYWdlRm9ybWF0SW5wdXQpID8gaW1hZ2VGb3JtYXRJbnB1dCA6ICdwbmcnXG5cbiAgY29uc3Qgc2NhbGVJbnB1dCA9IE51bWJlcihhcmdzLnNjYWxlID8/IDEpXG4gIGNvbnN0IGltYWdlU2NhbGUgPSBOdW1iZXIuaXNGaW5pdGUoc2NhbGVJbnB1dCkgJiYgc2NhbGVJbnB1dCA+IDAgPyBzY2FsZUlucHV0IDogMVxuXG4gIGNvbnN0IGlucHV0OiBUb29sSW5wdXQgPSB7XG4gICAgZmlsZUtleTogZmlsZUtleSA/PyBudWxsLFxuICAgIG5vZGVJZDogbm9kZUlkID8/IG51bGwsXG4gICAgaW5jbHVkZUltYWdlcyxcbiAgICBpbWFnZUZvcm1hdCxcbiAgICBzY2FsZTogaW1hZ2VTY2FsZSxcbiAgfVxuXG4gIGlmICghZmlsZUtleSkge1xuICAgIGVycm9ycy5wdXNoKGNyZWF0ZUVycm9yKCdJTlBVVF9JTlZBTElEJywgJ0EgdmFsaWQgRmlnbWEgZmlsZSBrZXkgaXMgcmVxdWlyZWQgKC0tZmlsZS1rZXkgb3IgLS11cmwpLicpKVxuICB9XG4gIGlmICghbm9kZUlkKSB7XG4gICAgZXJyb3JzLnB1c2goY3JlYXRlRXJyb3IoJ0lOUFVUX0lOVkFMSUQnLCAnQSB2YWxpZCBGaWdtYSBub2RlIGlkIGlzIHJlcXVpcmVkICgtLW5vZGUtaWQgb3IgLS11cmwgd2l0aCBub2RlLWlkKS4nKSlcbiAgfVxuICBpZiAoZXJyb3JzLmxlbmd0aCkge1xuICAgIGNvbnN0IGVudmVsb3BlID0gY3JlYXRlRW52ZWxvcGU8VG9vbElucHV0LCBFbXB0eURhdGE+KHsgdG9vbDogVE9PTF9OQU1FLCBpbnB1dCwgd2FybmluZ3MsIGVycm9ycywgZGF0YToge30gYXMgRW1wdHlEYXRhLCBzY2hlbWFWZXJzaW9uIH0pXG4gICAgZXhpdFdpdGhFbnZlbG9wZShlbnZlbG9wZSwgZXJyb3JzKVxuICB9XG5cbiAgY29uc3QgcmVzb2x2ZWRGaWxlS2V5ID0gZmlsZUtleSBhcyBzdHJpbmdcbiAgY29uc3QgcmVzb2x2ZWROb2RlSWQgPSBub2RlSWQgYXMgc3RyaW5nXG5cbiAgbG9nKGBGZXRjaGluZyBub2RlICR7cmVzb2x2ZWROb2RlSWR9IGZyb20gZmlsZSAke3Jlc29sdmVkRmlsZUtleX1gLCB2ZXJib3NlKVxuICBjb25zdCBub2RlUmVzcG9uc2UgPSBhd2FpdCBmaWdtYVJlcXVlc3Q8Tm9kZXNSZXNwb25zZT4oe1xuICAgIHBhdGg6IGAvdjEvZmlsZXMvJHtyZXNvbHZlZEZpbGVLZXl9L25vZGVzYCxcbiAgICB0b2tlbixcbiAgICBzZWFyY2hQYXJhbXM6IHsgaWRzOiByZXNvbHZlZE5vZGVJZCB9LFxuICB9KVxuXG4gIGlmICghbm9kZVJlc3BvbnNlLm9rKSB7XG4gICAgZXJyb3JzLnB1c2gobm9kZVJlc3BvbnNlLmVycm9yID8/IGNyZWF0ZUVycm9yKCdJTlRFUk5BTCcsICdGYWlsZWQgdG8gZmV0Y2ggbm9kZSBkYXRhLicpKVxuICAgIGNvbnN0IGVudmVsb3BlID0gY3JlYXRlRW52ZWxvcGU8VG9vbElucHV0LCBFbXB0eURhdGE+KHtcbiAgICAgIHRvb2w6IFRPT0xfTkFNRSxcbiAgICAgIGlucHV0LFxuICAgICAgd2FybmluZ3MsXG4gICAgICBlcnJvcnMsXG4gICAgICByYXRlTGltaXQ6IG5vZGVSZXNwb25zZS5yYXRlTGltaXQgPz8gdW5kZWZpbmVkLFxuICAgICAgZGF0YToge30gYXMgRW1wdHlEYXRhLFxuICAgICAgc2NoZW1hVmVyc2lvbixcbiAgICB9KVxuICAgIGV4aXRXaXRoRW52ZWxvcGUoZW52ZWxvcGUsIGVycm9ycylcbiAgfVxuXG4gIGNvbnN0IG5vZGVQYXlsb2FkID0gbm9kZVJlc3BvbnNlLmRhdGEgPz8ge31cbiAgY29uc3Qgbm9kZXNNYXAgPSBub2RlUGF5bG9hZC5ub2RlcyA/PyB7fVxuICBjb25zdCBub2RlV3JhcHBlciA9IG5vZGVzTWFwW3Jlc29sdmVkTm9kZUlkXVxuICBpZiAoIW5vZGVXcmFwcGVyIHx8ICFub2RlV3JhcHBlci5kb2N1bWVudCkge1xuICAgIGVycm9ycy5wdXNoKGNyZWF0ZUVycm9yKCdGSUdNQV9OT1RfRk9VTkQnLCBgTm9kZSAke3Jlc29sdmVkTm9kZUlkfSB3YXMgbm90IGZvdW5kIGluIGZpbGUgJHtyZXNvbHZlZEZpbGVLZXl9LmApKVxuICAgIGNvbnN0IGVudmVsb3BlID0gY3JlYXRlRW52ZWxvcGU8VG9vbElucHV0LCBFbXB0eURhdGE+KHsgdG9vbDogVE9PTF9OQU1FLCBpbnB1dCwgd2FybmluZ3MsIGVycm9ycywgcmF0ZUxpbWl0OiBub2RlUmVzcG9uc2UucmF0ZUxpbWl0ID8/IHVuZGVmaW5lZCwgZGF0YToge30gYXMgRW1wdHlEYXRhLCBzY2hlbWFWZXJzaW9uIH0pXG4gICAgZXhpdFdpdGhFbnZlbG9wZShlbnZlbG9wZSwgZXJyb3JzKVxuICB9XG5cbiAgY29uc3Qgbm9kZSA9IG5vZGVXcmFwcGVyLmRvY3VtZW50XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBub2RlV3JhcHBlci5jb21wb25lbnRzID8/IHt9XG4gIGNvbnN0IGNvbXBvbmVudFNldHMgPSBub2RlV3JhcHBlci5jb21wb25lbnRTZXRzID8/IHt9XG5cbiAgY29uc3Qgc2VsZWN0aW9uU3VtbWFyeSA9IGJ1aWxkU2VsZWN0aW9uU3VtbWFyeShub2RlLCBjb21wb25lbnRzLCBjb21wb25lbnRTZXRzKVxuICBjb25zdCBsYXlvdXRUcmVlID0gbWFwTGF5b3V0Tm9kZShub2RlKVxuICBjb25zdCBzdHlsZVRva2VucyA9IGJ1aWxkU3R5bGVUb2tlbnMobm9kZSlcbiAgY29uc3QgbGF5b3V0SGFzaCA9IGNvbXB1dGVMYXlvdXRIYXNoKGxheW91dFRyZWUpXG5cbiAgbGV0IHByZXZpZXc6IFByZXZpZXdJbWFnZSB8IG51bGwgPSBudWxsXG4gIGlmIChpbmNsdWRlSW1hZ2VzKSB7XG4gICAgcHJldmlldyA9IGF3YWl0IGZldGNoUHJldmlld0ltYWdlKFxuICAgICAgcmVzb2x2ZWRGaWxlS2V5LFxuICAgICAgcmVzb2x2ZWROb2RlSWQsXG4gICAgICB0b2tlbixcbiAgICAgIGltYWdlRm9ybWF0LFxuICAgICAgaW1hZ2VTY2FsZSxcbiAgICAgIHdhcm5pbmdzLFxuICAgICAgdmVyYm9zZVxuICAgIClcbiAgfVxuXG4gIGNvbnN0IGRhdGEgPSB7XG4gICAgZmlsZToge1xuICAgICAga2V5OiByZXNvbHZlZEZpbGVLZXksXG4gICAgICBuYW1lOiBub2RlUGF5bG9hZD8ubmFtZSA/PyBudWxsLFxuICAgICAgbGFzdE1vZGlmaWVkOiBub2RlUGF5bG9hZD8ubGFzdE1vZGlmaWVkID8/IG51bGwsXG4gICAgfSxcbiAgICBzZWxlY3Rpb25TdW1tYXJ5LFxuICAgIGxheW91dFRyZWUsXG4gICAgc3R5bGVUb2tlbnMsXG4gICAgbGF5b3V0SGFzaCxcbiAgICBpbWFnZXM6IHByZXZpZXcgPyB7IHByZXZpZXcgfSA6IG51bGwsXG4gIH1cblxuICBjb25zdCBlbnZlbG9wZSA9IGNyZWF0ZUVudmVsb3BlPFRvb2xJbnB1dCwgRGVzaWduQ29udGV4dERhdGE+KHtcbiAgICB0b29sOiBUT09MX05BTUUsXG4gICAgaW5wdXQsXG4gICAgZGF0YSxcbiAgICB3YXJuaW5ncyxcbiAgICBlcnJvcnMsXG4gICAgcmF0ZUxpbWl0OiBub2RlUmVzcG9uc2UucmF0ZUxpbWl0ID8/IHVuZGVmaW5lZCxcbiAgICBzY2hlbWFWZXJzaW9uLFxuICB9KVxuXG4gIHByb2Nlc3Muc3Rkb3V0LndyaXRlKGAke0pTT04uc3RyaW5naWZ5KGVudmVsb3BlLCBudWxsLCAyKX1cXG5gKVxuICBwcm9jZXNzLmV4aXQoZ2V0RXhpdENvZGUoZXJyb3JzKSlcbn1cblxubWFpbigpLmNhdGNoKChlcnJvcjogdW5rbm93bikgPT4ge1xuICBjb25zdCBtZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiAnVW5rbm93biBlcnJvcidcbiAgY29uc3QgZW52ZWxvcGUgPSBjcmVhdGVFbnZlbG9wZTxUb29sSW5wdXQsIEVtcHR5RGF0YT4oe1xuICAgIHRvb2w6IFRPT0xfTkFNRSxcbiAgICBpbnB1dDogeyBmaWxlS2V5OiBudWxsLCBub2RlSWQ6IG51bGwsIGluY2x1ZGVJbWFnZXM6IGZhbHNlLCBpbWFnZUZvcm1hdDogJ3BuZycsIHNjYWxlOiAxIH0sXG4gICAgZXJyb3JzOiBbY3JlYXRlRXJyb3IoJ0lOVEVSTkFMJywgbWVzc2FnZSwgeyBzdGFjazogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLnN0YWNrIDogdW5kZWZpbmVkIH0pXSxcbiAgICBkYXRhOiB7fSBhcyBFbXB0eURhdGEsXG4gIH0pXG4gIHByb2Nlc3Muc3Rkb3V0LndyaXRlKGAke0pTT04uc3RyaW5naWZ5KGVudmVsb3BlLCBudWxsLCAyKX1cXG5gKVxuICBwcm9jZXNzLmV4aXQoMylcbn0pXG5cbiIsICJleHBvcnQgdHlwZSBDbGlBcmdWYWx1ZSA9IHN0cmluZyB8IGJvb2xlYW47XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xpQXJncyB7XG4gIF86IHN0cmluZ1tdO1xuICBba2V5OiBzdHJpbmddOiBDbGlBcmdWYWx1ZSB8IHN0cmluZ1tdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VBcmdzKGFyZ3Y6IHN0cmluZ1tdID0gcHJvY2Vzcy5hcmd2LnNsaWNlKDIpKTogQ2xpQXJncyB7XG4gIGNvbnN0IGFyZ3M6IENsaUFyZ3MgPSB7IF86IFtdIH07XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcmd2Lmxlbmd0aDsgaSArPSAxKSB7XG4gICAgY29uc3QgYXJnID0gYXJndltpXTtcblxuICAgIGlmICghYXJnLnN0YXJ0c1dpdGgoJy0nKSB8fCBhcmcgPT09ICctJykge1xuICAgICAgYXJncy5fLnB1c2goYXJnKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmIChhcmcgPT09ICctLScpIHtcbiAgICAgIGNvbnN0IHJlbWFpbmluZyA9IGFyZ3Yuc2xpY2UoaSArIDEpO1xuICAgICAgYXJncy5fLnB1c2goLi4ucmVtYWluaW5nKTtcbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGNvbnN0IFtyYXdLZXksIGlubGluZVZhbHVlXSA9IGFyZy5zcGxpdCgnPScsIDIpO1xuICAgIGNvbnN0IG5vcm1hbGlzZWRLZXkgPSByYXdLZXkucmVwbGFjZSgvXi0rLywgJycpO1xuXG4gICAgbGV0IHZhbHVlOiBDbGlBcmdWYWx1ZTtcbiAgICBpZiAoaW5saW5lVmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdmFsdWUgPSBpbmxpbmVWYWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgbmV4dCA9IGFyZ3ZbaSArIDFdO1xuICAgICAgaWYgKG5leHQgIT09IHVuZGVmaW5lZCAmJiAhbmV4dC5zdGFydHNXaXRoKCctJykpIHtcbiAgICAgICAgdmFsdWUgPSBuZXh0O1xuICAgICAgICBpICs9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YWx1ZSA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgYXJnc1tub3JtYWxpc2VkS2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgcmV0dXJuIGFyZ3M7XG59XG5cbiIsICJleHBvcnQgZGVmYXVsdCB7XG4gIHNjaGVtYVZlcnNpb246ICcxLjAuMCcsXG4gIHNvdXJjZTogJ2FnZW50aWMtY29kaW5nLXRlbXBsYXRlcy9maWdtYS10b29scycsXG4gIGh0dHA6IHtcbiAgICBtYXhBdHRlbXB0czogNSxcbiAgICBpbml0aWFsRGVsYXlNczogMjUwLFxuICB9LFxufSBhcyBjb25zdDtcblxuIiwgImltcG9ydCBjb25maWcgZnJvbSAnLi9jb25maWcudHMnO1xuaW1wb3J0IHR5cGUgeyBUb29sRXJyb3IgfSBmcm9tICcuL2Vycm9ycy50cyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmF0ZUxpbWl0TWV0YSB7XG4gIHJlbWFpbmluZzogbnVtYmVyIHwgbnVsbDtcbiAgcmVzZXRBdDogc3RyaW5nIHwgbnVsbDtcbiAgYXR0ZW1wdHM6IG51bWJlcjtcbiAgbGFzdFdhaXRNczogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRvb2xFbnZlbG9wZTxcbiAgVElucHV0IGV4dGVuZHMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgVERhdGEgPSB1bmtub3duXG4+IHtcbiAgc2NoZW1hVmVyc2lvbjogc3RyaW5nO1xuICB0b29sOiBzdHJpbmc7XG4gIGlucHV0OiBUSW5wdXQ7XG4gIG1ldGE6IHtcbiAgICBnZW5lcmF0ZWRBdDogc3RyaW5nO1xuICAgIHNvdXJjZTogc3RyaW5nO1xuICAgIHJhdGVMaW1pdDogUmF0ZUxpbWl0TWV0YTtcbiAgfTtcbiAgZGF0YTogVERhdGE7XG4gIHdhcm5pbmdzOiBzdHJpbmdbXTtcbiAgZXJyb3JzOiBUb29sRXJyb3JbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVFbnZlbG9wZU9wdGlvbnM8XG4gIFRJbnB1dCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIFREYXRhID0gdW5rbm93blxuPiB7XG4gIHRvb2w6IHN0cmluZztcbiAgaW5wdXQ/OiBUSW5wdXQ7XG4gIGRhdGE/OiBURGF0YTtcbiAgd2FybmluZ3M/OiBzdHJpbmdbXTtcbiAgZXJyb3JzPzogVG9vbEVycm9yW107XG4gIHJhdGVMaW1pdD86IFBhcnRpYWw8UmF0ZUxpbWl0TWV0YT47XG4gIHNjaGVtYVZlcnNpb24/OiBzdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkUmF0ZUxpbWl0TWV0YShyYXRlTGltaXQ6IFBhcnRpYWw8UmF0ZUxpbWl0TWV0YT4gPSB7fSk6IFJhdGVMaW1pdE1ldGEge1xuICByZXR1cm4ge1xuICAgIHJlbWFpbmluZzogcmF0ZUxpbWl0LnJlbWFpbmluZyA/PyBudWxsLFxuICAgIHJlc2V0QXQ6IHJhdGVMaW1pdC5yZXNldEF0ID8/IG51bGwsXG4gICAgYXR0ZW1wdHM6IHJhdGVMaW1pdC5hdHRlbXB0cyA/PyAxLFxuICAgIGxhc3RXYWl0TXM6IHJhdGVMaW1pdC5sYXN0V2FpdE1zID8/IDAsXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFbnZlbG9wZTxcbiAgVElucHV0IGV4dGVuZHMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgVERhdGEgPSB1bmtub3duXG4+KHtcbiAgdG9vbCxcbiAgaW5wdXQgPSB7fSBhcyBUSW5wdXQsXG4gIGRhdGEgPSB7fSBhcyBURGF0YSxcbiAgd2FybmluZ3MgPSBbXSxcbiAgZXJyb3JzID0gW10sXG4gIHJhdGVMaW1pdCxcbiAgc2NoZW1hVmVyc2lvbixcbn06IENyZWF0ZUVudmVsb3BlT3B0aW9uczxUSW5wdXQsIFREYXRhPik6IFRvb2xFbnZlbG9wZTxUSW5wdXQsIFREYXRhPiB7XG4gIHJldHVybiB7XG4gICAgc2NoZW1hVmVyc2lvbjogc2NoZW1hVmVyc2lvbiA/PyBjb25maWcuc2NoZW1hVmVyc2lvbixcbiAgICB0b29sLFxuICAgIGlucHV0LFxuICAgIG1ldGE6IHtcbiAgICAgIGdlbmVyYXRlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICBzb3VyY2U6IGNvbmZpZy5zb3VyY2UsXG4gICAgICByYXRlTGltaXQ6IGJ1aWxkUmF0ZUxpbWl0TWV0YShyYXRlTGltaXQpLFxuICAgIH0sXG4gICAgZGF0YSxcbiAgICB3YXJuaW5ncyxcbiAgICBlcnJvcnMsXG4gIH07XG59XG5cbiIsICJleHBvcnQgY29uc3QgRVJST1JfRVhJVF9DT0RFUyA9IHtcbiAgSU5QVVRfSU5WQUxJRDogMSxcbiAgQ09ORklHX0lOVkFMSUQ6IDEsXG4gIEZJR01BX0FVVEg6IDEsXG4gIEZJR01BX05PVF9GT1VORDogMixcbiAgRklHTUFfUkFURV9MSU1JVDogMixcbiAgTkVUV09SSzogMixcbiAgSU5URVJOQUw6IDMsXG59IGFzIGNvbnN0O1xuXG5leHBvcnQgdHlwZSBFcnJvckNvZGUgPSBrZXlvZiB0eXBlb2YgRVJST1JfRVhJVF9DT0RFUztcblxuZXhwb3J0IGludGVyZmFjZSBUb29sRXJyb3I8VERldGFpbCA9IHVua25vd24+IHtcbiAgY29kZTogRXJyb3JDb2RlIHwgc3RyaW5nO1xuICBtZXNzYWdlOiBzdHJpbmc7XG4gIGRldGFpbD86IFREZXRhaWwgfCBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRXJyb3I8VERldGFpbCA9IHVua25vd24+KFxuICBjb2RlOiBFcnJvckNvZGUgfCBzdHJpbmcsXG4gIG1lc3NhZ2U6IHN0cmluZyxcbiAgZGV0YWlsPzogVERldGFpbCB8IG51bGxcbik6IFRvb2xFcnJvcjxURGV0YWlsPiB7XG4gIHJldHVybiB7XG4gICAgY29kZSxcbiAgICBtZXNzYWdlLFxuICAgIGRldGFpbDogZGV0YWlsID8/IG51bGwsXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRFeGl0Q29kZShlcnJvcnM6IFRvb2xFcnJvcltdID0gW10pOiBudW1iZXIge1xuICBpZiAoIWVycm9ycy5sZW5ndGgpIHtcbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIHJldHVybiBlcnJvcnMucmVkdWNlKChtYXgsIGVycm9yKSA9PiB7XG4gICAgY29uc3QgZXhpdENvZGUgPSBFUlJPUl9FWElUX0NPREVTW2Vycm9yLmNvZGUgYXMgRXJyb3JDb2RlXSA/PyAxO1xuICAgIHJldHVybiBNYXRoLm1heChtYXgsIGV4aXRDb2RlKTtcbiAgfSwgMCk7XG59XG5cbiIsICJpbXBvcnQgY29uZmlnIGZyb20gJy4vY29uZmlnLnRzJztcbmltcG9ydCB7IGNyZWF0ZUVycm9yIH0gZnJvbSAnLi9lcnJvcnMudHMnO1xuaW1wb3J0IHR5cGUgeyBUb29sRXJyb3IgfSBmcm9tICcuL2Vycm9ycy50cyc7XG5pbXBvcnQgdHlwZSB7IFJhdGVMaW1pdE1ldGEgfSBmcm9tICcuL2VudmVsb3BlLnRzJztcblxuY29uc3QgQkFTRV9VUkwgPSAnaHR0cHM6Ly9hcGkuZmlnbWEuY29tJztcblxudHlwZSBTZWFyY2hQYXJhbXMgPSBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgbnVsbCB8IHVuZGVmaW5lZD47XG5cbmludGVyZmFjZSBGaWdtYVJlcXVlc3RPcHRpb25zIHtcbiAgcGF0aDogc3RyaW5nO1xuICBtZXRob2Q/OiBzdHJpbmc7XG4gIHRva2VuPzogc3RyaW5nO1xuICBoZWFkZXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgYm9keT86IHVua25vd247XG4gIHNlYXJjaFBhcmFtcz86IFNlYXJjaFBhcmFtcztcbiAgbWF4QXR0ZW1wdHM/OiBudW1iZXI7XG4gIGluaXRpYWxEZWxheU1zPzogbnVtYmVyO1xufVxuXG5pbnRlcmZhY2UgRmlnbWFTdWNjZXNzPFREYXRhPiB7XG4gIG9rOiB0cnVlO1xuICBkYXRhOiBURGF0YTtcbiAgcmF0ZUxpbWl0OiBSYXRlTGltaXRNZXRhO1xufVxuXG5pbnRlcmZhY2UgRmlnbWFGYWlsdXJlIHtcbiAgb2s6IGZhbHNlO1xuICBlcnJvcjogVG9vbEVycm9yPHsgc3RhdHVzPzogbnVtYmVyIH0+O1xuICBzdGF0dXM/OiBudW1iZXIgfCBudWxsO1xuICByYXRlTGltaXQ6IFJhdGVMaW1pdE1ldGEgfCBudWxsO1xufVxuXG5leHBvcnQgdHlwZSBGaWdtYVJlc3BvbnNlPFREYXRhPiA9IEZpZ21hU3VjY2VzczxURGF0YT4gfCBGaWdtYUZhaWx1cmU7XG5cbmZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG59XG5cbmZ1bmN0aW9uIHBhcnNlSnNvblNhZmVseSh0ZXh0OiBzdHJpbmcpOiB1bmtub3duIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gdGV4dCA/IEpTT04ucGFyc2UodGV4dCkgOiB7fTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHsgcmF3OiB0ZXh0IH07XG4gIH1cbn1cblxuZnVuY3Rpb24gcGFyc2VSYXRlTGltaXQoaGVhZGVyczogSGVhZGVycywgYXR0ZW1wdHM6IG51bWJlciwgbGFzdFdhaXRNczogbnVtYmVyKTogUmF0ZUxpbWl0TWV0YSB7XG4gIGNvbnN0IHJlbWFpbmluZ0hlYWRlciA9IGhlYWRlcnMuZ2V0KCd4LXJhdGVsaW1pdC1yZW1haW5pbmcnKTtcbiAgY29uc3QgcmVzZXRIZWFkZXIgPSBoZWFkZXJzLmdldCgneC1yYXRlbGltaXQtcmVzZXQnKTtcblxuICBsZXQgcmVtYWluaW5nOiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgaWYgKHJlbWFpbmluZ0hlYWRlciAhPT0gbnVsbCAmJiByZW1haW5pbmdIZWFkZXIgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IHBhcnNlZCA9IE51bWJlcihyZW1haW5pbmdIZWFkZXIpO1xuICAgIHJlbWFpbmluZyA9IE51bWJlci5pc05hTihwYXJzZWQpID8gbnVsbCA6IHBhcnNlZDtcbiAgfVxuXG4gIGxldCByZXNldEF0OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgaWYgKHJlc2V0SGVhZGVyKSB7XG4gICAgY29uc3QgbnVtZXJpY1Jlc2V0ID0gTnVtYmVyKHJlc2V0SGVhZGVyKTtcbiAgICBpZiAoIU51bWJlci5pc05hTihudW1lcmljUmVzZXQpKSB7XG4gICAgICByZXNldEF0ID0gbmV3IERhdGUobnVtZXJpY1Jlc2V0ICogMTAwMCkudG9JU09TdHJpbmcoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKHJlc2V0SGVhZGVyKTtcbiAgICAgIGlmICghTnVtYmVyLmlzTmFOKGRhdGUudmFsdWVPZigpKSkge1xuICAgICAgICByZXNldEF0ID0gZGF0ZS50b0lTT1N0cmluZygpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgcmVtYWluaW5nLFxuICAgIHJlc2V0QXQsXG4gICAgYXR0ZW1wdHMsXG4gICAgbGFzdFdhaXRNcyxcbiAgfTtcbn1cblxuZnVuY3Rpb24gY29tcHV0ZUJhY2tvZmZNcyhhdHRlbXB0OiBudW1iZXIsIGluaXRpYWxEZWxheU1zOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gaW5pdGlhbERlbGF5TXMgKiAyICoqIChhdHRlbXB0IC0gMSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmaWdtYVJlcXVlc3Q8VERhdGEgPSB1bmtub3duPihcbiAgb3B0aW9uczogRmlnbWFSZXF1ZXN0T3B0aW9uc1xuKTogUHJvbWlzZTxGaWdtYVJlc3BvbnNlPFREYXRhPj4ge1xuICBjb25zdCB7XG4gICAgcGF0aCxcbiAgICBtZXRob2QgPSAnR0VUJyxcbiAgICB0b2tlbixcbiAgICBoZWFkZXJzID0ge30sXG4gICAgYm9keSxcbiAgICBzZWFyY2hQYXJhbXMsXG4gICAgbWF4QXR0ZW1wdHMgPSBjb25maWcuaHR0cD8ubWF4QXR0ZW1wdHMgPz8gNSxcbiAgICBpbml0aWFsRGVsYXlNcyA9IGNvbmZpZy5odHRwPy5pbml0aWFsRGVsYXlNcyA/PyAyNTAsXG4gIH0gPSBvcHRpb25zO1xuXG4gIGlmICghdG9rZW4pIHtcbiAgICByZXR1cm4ge1xuICAgICAgb2s6IGZhbHNlLFxuICAgICAgZXJyb3I6IGNyZWF0ZUVycm9yKCdGSUdNQV9BVVRIJywgJ0ZJR01BX0FDQ0VTU19UT0tFTiBpcyBtaXNzaW5nIGZyb20gdGhlIGVudmlyb25tZW50LicpLFxuICAgICAgc3RhdHVzOiBudWxsLFxuICAgICAgcmF0ZUxpbWl0OiBudWxsLFxuICAgIH07XG4gIH1cblxuICBjb25zdCB1cmwgPSBuZXcgVVJMKHBhdGgsIEJBU0VfVVJMKTtcblxuICBpZiAoc2VhcmNoUGFyYW1zKSB7XG4gICAgT2JqZWN0LmVudHJpZXMoc2VhcmNoUGFyYW1zKS5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBudWxsKSByZXR1cm47XG4gICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChrZXksIFN0cmluZyh2YWx1ZSkpO1xuICAgIH0pO1xuICB9XG5cbiAgbGV0IGF0dGVtcHQgPSAwO1xuICBsZXQgbGFzdFdhaXRNcyA9IDA7XG5cbiAgd2hpbGUgKGF0dGVtcHQgPCBtYXhBdHRlbXB0cykge1xuICAgIGF0dGVtcHQgKz0gMTtcblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsLCB7XG4gICAgICBtZXRob2QsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICdYLUZpZ21hLVRva2VuJzogdG9rZW4sXG4gICAgICAgIC4uLmhlYWRlcnMsXG4gICAgICB9LFxuICAgICAgYm9keTogYm9keSA/IEpTT04uc3RyaW5naWZ5KGJvZHkpIDogdW5kZWZpbmVkLFxuICAgIH0pO1xuXG4gICAgY29uc3QgdGV4dCA9IGF3YWl0IHJlc3BvbnNlLnRleHQoKTtcbiAgICBjb25zdCBwYXlsb2FkID0gcGFyc2VKc29uU2FmZWx5KHRleHQpIGFzIHsgbWVzc2FnZT86IHN0cmluZyB9O1xuICAgIGNvbnN0IHJhdGVMaW1pdCA9IHBhcnNlUmF0ZUxpbWl0KHJlc3BvbnNlLmhlYWRlcnMsIGF0dGVtcHQsIGxhc3RXYWl0TXMpO1xuXG4gICAgaWYgKHJlc3BvbnNlLm9rKSB7XG4gICAgICByZXR1cm4geyBvazogdHJ1ZSwgZGF0YTogcGF5bG9hZCBhcyBURGF0YSwgcmF0ZUxpbWl0IH07XG4gICAgfVxuXG4gICAgY29uc3Qgc3RhdHVzID0gcmVzcG9uc2Uuc3RhdHVzO1xuXG4gICAgaWYgKHN0YXR1cyA9PT0gNDAxIHx8IHN0YXR1cyA9PT0gNDAzKSB7XG4gICAgICByZXR1cm4geyBvazogZmFsc2UsIGVycm9yOiBjcmVhdGVFcnJvcignRklHTUFfQVVUSCcsIHBheWxvYWQ/Lm1lc3NhZ2UgPz8gJ0ZpZ21hIHRva2VuIGlzIHVuYXV0aG9yaXplZC4nLCB7IHN0YXR1cyB9KSwgc3RhdHVzLCByYXRlTGltaXQgfTtcbiAgICB9XG5cbiAgICBpZiAoc3RhdHVzID09PSA0MDQpIHtcbiAgICAgIHJldHVybiB7IG9rOiBmYWxzZSwgZXJyb3I6IGNyZWF0ZUVycm9yKCdGSUdNQV9OT1RfRk9VTkQnLCBwYXlsb2FkPy5tZXNzYWdlID8/ICdSZXNvdXJjZSBub3QgZm91bmQuJywgeyBzdGF0dXMgfSksIHN0YXR1cywgcmF0ZUxpbWl0IH07XG4gICAgfVxuXG4gICAgaWYgKHN0YXR1cyA9PT0gNDI5IHx8IHN0YXR1cyA+PSA1MDApIHtcbiAgICAgIGlmIChhdHRlbXB0ID49IG1heEF0dGVtcHRzKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgb2s6IGZhbHNlLFxuICAgICAgICAgIGVycm9yOiBjcmVhdGVFcnJvcihzdGF0dXMgPT09IDQyOSA/ICdGSUdNQV9SQVRFX0xJTUlUJyA6ICdORVRXT1JLJywgcGF5bG9hZD8ubWVzc2FnZSA/PyAnRmlnbWEgcmVxdWVzdCBmYWlsZWQgYWZ0ZXIgbWF4aW11bSByZXRyaWVzLicsIHsgc3RhdHVzIH0pLFxuICAgICAgICAgIHN0YXR1cyxcbiAgICAgICAgICByYXRlTGltaXQsXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGxldCB3YWl0TXMgPSBjb21wdXRlQmFja29mZk1zKGF0dGVtcHQsIGluaXRpYWxEZWxheU1zKTtcbiAgICAgIGNvbnN0IHJlc2V0SGVhZGVyID0gcmVzcG9uc2UuaGVhZGVycy5nZXQoJ3gtcmF0ZWxpbWl0LXJlc2V0Jyk7XG4gICAgICBpZiAocmVzZXRIZWFkZXIpIHtcbiAgICAgICAgY29uc3QgYXNOdW1iZXIgPSBOdW1iZXIocmVzZXRIZWFkZXIpO1xuICAgICAgICBpZiAoIU51bWJlci5pc05hTihhc051bWJlcikpIHtcbiAgICAgICAgICBjb25zdCByZXNldE1zID0gYXNOdW1iZXIgKiAxMDAwO1xuICAgICAgICAgIGNvbnN0IGRlbHRhID0gcmVzZXRNcyAtIERhdGUubm93KCk7XG4gICAgICAgICAgaWYgKGRlbHRhID4gMCkgd2FpdE1zID0gTWF0aC5tYXgod2FpdE1zLCBkZWx0YSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qgaml0dGVyID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMTAwKTtcbiAgICAgIGxhc3RXYWl0TXMgPSB3YWl0TXMgKyBqaXR0ZXI7XG4gICAgICBhd2FpdCBzbGVlcChsYXN0V2FpdE1zKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHJldHVybiB7IG9rOiBmYWxzZSwgZXJyb3I6IGNyZWF0ZUVycm9yKCdJTlRFUk5BTCcsIHBheWxvYWQ/Lm1lc3NhZ2UgPz8gJ1VuZXhwZWN0ZWQgZXJyb3IgZnJvbSBGaWdtYSBBUEkuJywgeyBzdGF0dXMgfSksIHN0YXR1cywgcmF0ZUxpbWl0IH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG9rOiBmYWxzZSxcbiAgICBlcnJvcjogY3JlYXRlRXJyb3IoJ05FVFdPUksnLCAnVW5hYmxlIHRvIHJlYWNoIEZpZ21hIEFQSS4nKSxcbiAgICBzdGF0dXM6IG51bGwsXG4gICAgcmF0ZUxpbWl0OiB7IHJlbWFpbmluZzogbnVsbCwgcmVzZXRBdDogbnVsbCwgYXR0ZW1wdHM6IG1heEF0dGVtcHRzLCBsYXN0V2FpdE1zIH0sXG4gIH07XG59XG5cbiIsICJjb25zdCBGSUxFX0tFWV9SRUdFWCA9IC9maWdtYVxcLmNvbVxcLyg/OmZpbGV8ZGVzaWduKVxcLyhbQS1aYS16MC05XSspXFwvL2k7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFyc2VkRmlnbWFVcmwge1xuICBmaWxlS2V5OiBzdHJpbmcgfCBudWxsO1xuICBub2RlSWQ6IHN0cmluZyB8IG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUZpZ21hVXJsKGlucHV0OiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogUGFyc2VkRmlnbWFVcmwge1xuICBpZiAoIWlucHV0KSByZXR1cm4geyBmaWxlS2V5OiBudWxsLCBub2RlSWQ6IG51bGwgfTtcbiAgdHJ5IHtcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKGlucHV0KTtcbiAgICBjb25zdCBtYXRjaCA9IHVybC5ocmVmLm1hdGNoKEZJTEVfS0VZX1JFR0VYKTtcbiAgICBjb25zdCBmaWxlS2V5ID0gbWF0Y2ggPyBtYXRjaFsxXSA6IG51bGw7XG4gICAgY29uc3Qgbm9kZVBhcmFtID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ25vZGUtaWQnKTtcbiAgICBjb25zdCBub2RlSWQgPSBub2RlUGFyYW0gPyBlbnN1cmVOb2RlSWQobm9kZVBhcmFtKSA6IG51bGw7XG4gICAgcmV0dXJuIHsgZmlsZUtleSwgbm9kZUlkIH07XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB7IGZpbGVLZXk6IG51bGwsIG5vZGVJZDogbnVsbCB9O1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVOb2RlSWQodmFsdWU6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCBudWxsIHtcbiAgaWYgKCF2YWx1ZSkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IGRlY29kZWQgPSBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpO1xuICBpZiAoZGVjb2RlZC5pbmNsdWRlcygnOicpKSByZXR1cm4gZGVjb2RlZDtcbiAgaWYgKC9eWzAtOV0rLVswLTldKyQvLnRlc3QoZGVjb2RlZCkpIHtcbiAgICBjb25zdCBbbGVmdCwgcmlnaHRdID0gZGVjb2RlZC5zcGxpdCgnLScsIDIpO1xuICAgIHJldHVybiBgJHtsZWZ0fToke3JpZ2h0fWA7XG4gIH1cbiAgcmV0dXJuIGRl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