#!/usr/bin/env node // coding-tools/figma-tools/js/src/get-code-connect-map.ts import { readFile } from "node:fs/promises"; import path from "node:path"; // 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/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/_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: path2, 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(path2, 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/get-code-connect-map.ts var TOOL_NAME = "get-code-connect-map"; 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)); } async function readRepoConfig() { try { const configPath = path.resolve("config/code-connect-map.json"); const content = await readFile(configPath, "utf8"); const parsed = JSON.parse(content); if (parsed && Array.isArray(parsed.components)) return parsed; return { version: "0.1", components: [] }; } catch { return { version: "0.1", components: [] }; } } 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 = []; let repoConfig = { version: "0.1", components: [] }; try { repoConfig = await readRepoConfig(); } catch (error) { warnings.push(error instanceof Error ? error.message : String(error)); } 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 }, warnings, errors, schemaVersion, data: {} }); exitWithEnvelope(envelope2, errors); } const urlInput = toOptionalString(args.url) ?? toOptionalString(args.u); let fileKey = toOptionalString(args["file-key"]) ?? void 0; const nodeIdInput = ensureNodeId(toOptionalString(args["node-id"])); if (urlInput) { const parsed = parseFigmaUrl(urlInput); fileKey = fileKey || parsed.fileKey || void 0; } const input = { fileKey: fileKey ?? null, nodeId: nodeIdInput ?? null }; if (!fileKey) errors.push(createError("INPUT_INVALID", "A valid Figma file key is required (--file-key or --url).")); if (errors.length) { const envelope2 = createEnvelope({ tool: TOOL_NAME, input, warnings, errors, data: {}, schemaVersion }); exitWithEnvelope(envelope2, errors); } const resolvedFileKey = fileKey; log("Fetching dev resources", verbose); const devResourcesResponse = await figmaRequest({ path: `/v1/files/${resolvedFileKey}/devresources`, token }); log("Fetching components", verbose); const componentsResponse = await figmaRequest({ path: `/v1/files/${resolvedFileKey}/components`, token }); if (!devResourcesResponse.ok) { errors.push(devResourcesResponse.error ?? createError("INTERNAL", "Failed to fetch dev resources.")); const envelope2 = createEnvelope({ tool: TOOL_NAME, input, warnings, errors, rateLimit: devResourcesResponse.rateLimit ?? void 0, schemaVersion, data: {} }); exitWithEnvelope(envelope2, errors); } if (!componentsResponse.ok) warnings.push(componentsResponse.error?.message ?? "Failed to fetch components."); const devResources = devResourcesResponse.data?.dev_resources ?? []; const componentsMap = componentsResponse.ok ? componentsResponse.data?.components ?? {} : {}; const repoMappings = repoConfig.components ?? []; const normalisedResources = devResources.map((resource) => ({ id: resource.id, name: resource.name, description: resource.description ?? null, url: resource.url ?? null, nodeId: resource.node_id ?? null, componentId: resource.component_id ?? null, fileKey: resource.file_key ?? resolvedFileKey, status: resource.status ?? null, createdAt: resource.created_at ?? null, updatedAt: resource.updated_at ?? null })); const normalisedComponents = Object.entries(componentsMap).map(([componentId, component]) => ({ id: componentId, key: component.key, name: component.name, description: component.description ?? null, fileKey: component.file_key ?? resolvedFileKey, nodeId: component.node_id ?? null })); const findRepoMapping = (name) => { if (!name) return null; return repoMappings.find((m) => m.name === name || m.component === name) ?? null; }; const mappings = normalisedResources.map((resource) => { const component = resource.componentId ? normalisedComponents.find((entry) => entry.id === resource.componentId) : null; const repoMapping = findRepoMapping(component?.name ?? resource.name); if (!repoMapping) { warnings.push(`Node ${resource.nodeId ?? component?.nodeId ?? "unknown"} (${resource.name ?? component?.name ?? "unnamed"}) has no mapping in config/code-connect-map.json.`); } return { nodeId: resource.nodeId ?? component?.nodeId ?? null, componentId: resource.componentId ?? component?.id ?? null, componentKey: component?.key ?? null, componentName: component?.name ?? resource.name ?? null, repoComponent: repoMapping?.component ?? null, repoPath: repoMapping?.path ?? null, props: repoMapping?.props ?? null, description: component?.description ?? resource.description ?? null, status: resource.status ?? null, sourceUrl: resource.url ?? null }; }); const data = { file: { key: resolvedFileKey }, mappings, components: normalisedComponents, devResources: normalisedResources }; const envelope = createEnvelope({ tool: TOOL_NAME, input, data, warnings, errors, rateLimit: devResourcesResponse.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 }, 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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2dldC1jb2RlLWNvbm5lY3QtbWFwLnRzIiwgIi4uL3NyYy9fdXRpbHMvY2xpLWFyZ3MudHMiLCAiLi4vc3JjL191dGlscy91cmwtcGFyc2UudHMiLCAiLi4vc3JjL191dGlscy9jb25maWcudHMiLCAiLi4vc3JjL191dGlscy9lbnZlbG9wZS50cyIsICIuLi9zcmMvX3V0aWxzL2Vycm9ycy50cyIsICIuLi9zcmMvX3V0aWxzL2h0dHAtY2xpZW50LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIjIS91c3IvYmluL2VudiBub2RlXG5cbmltcG9ydCB7IHJlYWRGaWxlIH0gZnJvbSAnbm9kZTpmcy9wcm9taXNlcydcbmltcG9ydCBwYXRoIGZyb20gJ25vZGU6cGF0aCdcbmltcG9ydCB7IHBhcnNlQXJncywgdHlwZSBDbGlBcmdzIH0gZnJvbSAnLi9fdXRpbHMvY2xpLWFyZ3MudHMnXG5pbXBvcnQgeyBwYXJzZUZpZ21hVXJsLCBlbnN1cmVOb2RlSWQgfSBmcm9tICcuL191dGlscy91cmwtcGFyc2UudHMnXG5pbXBvcnQgeyBjcmVhdGVFbnZlbG9wZSwgdHlwZSBUb29sRW52ZWxvcGUgfSBmcm9tICcuL191dGlscy9lbnZlbG9wZS50cydcbmltcG9ydCB7IGNyZWF0ZUVycm9yLCBnZXRFeGl0Q29kZSwgdHlwZSBUb29sRXJyb3IgfSBmcm9tICcuL191dGlscy9lcnJvcnMudHMnXG5pbXBvcnQgeyBmaWdtYVJlcXVlc3QgfSBmcm9tICcuL191dGlscy9odHRwLWNsaWVudC50cydcblxuY29uc3QgVE9PTF9OQU1FID0gJ2dldC1jb2RlLWNvbm5lY3QtbWFwJ1xudHlwZSBFbXB0eURhdGEgPSBSZWNvcmQ8c3RyaW5nLCBuZXZlcj5cblxuaW50ZXJmYWNlIFRvb2xJbnB1dCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHsgZmlsZUtleTogc3RyaW5nIHwgbnVsbDsgbm9kZUlkOiBzdHJpbmcgfCBudWxsIH1cblxuaW50ZXJmYWNlIFJlcG9Db21wb25lbnRNYXBwaW5nIHsgbmFtZT86IHN0cmluZzsgY29tcG9uZW50Pzogc3RyaW5nOyBwYXRoPzogc3RyaW5nOyBwcm9wcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH1cbmludGVyZmFjZSBSZXBvQ29uZmlnIHsgdmVyc2lvbj86IHN0cmluZzsgY29tcG9uZW50cz86IFJlcG9Db21wb25lbnRNYXBwaW5nW10gfVxuXG5pbnRlcmZhY2UgRGV2UmVzb3VyY2VQYXlsb2FkIHsgZGV2X3Jlc291cmNlcz86IERldlJlc291cmNlW10gfVxuaW50ZXJmYWNlIERldlJlc291cmNlIHsgaWQ6IHN0cmluZzsgbmFtZT86IHN0cmluZzsgZGVzY3JpcHRpb24/OiBzdHJpbmc7IHVybD86IHN0cmluZzsgbm9kZV9pZD86IHN0cmluZzsgY29tcG9uZW50X2lkPzogc3RyaW5nOyBmaWxlX2tleT86IHN0cmluZzsgc3RhdHVzPzogc3RyaW5nOyBjcmVhdGVkX2F0Pzogc3RyaW5nOyB1cGRhdGVkX2F0Pzogc3RyaW5nIH1cbmludGVyZmFjZSBOb3JtYWxpc2VkRGV2UmVzb3VyY2UgeyBpZDogc3RyaW5nOyBuYW1lPzogc3RyaW5nOyBkZXNjcmlwdGlvbjogc3RyaW5nIHwgbnVsbDsgdXJsOiBzdHJpbmcgfCBudWxsOyBub2RlSWQ6IHN0cmluZyB8IG51bGw7IGNvbXBvbmVudElkOiBzdHJpbmcgfCBudWxsOyBmaWxlS2V5OiBzdHJpbmc7IHN0YXR1czogc3RyaW5nIHwgbnVsbDsgY3JlYXRlZEF0OiBzdHJpbmcgfCBudWxsOyB1cGRhdGVkQXQ6IHN0cmluZyB8IG51bGwgfVxuXG5pbnRlcmZhY2UgQ29tcG9uZW50TWV0YSB7IGtleT86IHN0cmluZzsgbmFtZT86IHN0cmluZzsgZGVzY3JpcHRpb24/OiBzdHJpbmc7IGZpbGVfa2V5Pzogc3RyaW5nOyBub2RlX2lkPzogc3RyaW5nIH1cbmludGVyZmFjZSBDb21wb25lbnRzUGF5bG9hZCB7IGNvbXBvbmVudHM/OiBSZWNvcmQ8c3RyaW5nLCBDb21wb25lbnRNZXRhPiB9XG5pbnRlcmZhY2UgTm9ybWFsaXNlZENvbXBvbmVudCB7IGlkOiBzdHJpbmc7IGtleT86IHN0cmluZzsgbmFtZT86IHN0cmluZzsgZGVzY3JpcHRpb246IHN0cmluZyB8IG51bGw7IGZpbGVLZXk6IHN0cmluZzsgbm9kZUlkOiBzdHJpbmcgfCBudWxsIH1cblxuaW50ZXJmYWNlIE1hcHBpbmcgeyBub2RlSWQ6IHN0cmluZyB8IG51bGw7IGNvbXBvbmVudElkOiBzdHJpbmcgfCBudWxsOyBjb21wb25lbnRLZXk6IHN0cmluZyB8IG51bGw7IGNvbXBvbmVudE5hbWU6IHN0cmluZyB8IG51bGw7IHJlcG9Db21wb25lbnQ6IHN0cmluZyB8IG51bGw7IHJlcG9QYXRoOiBzdHJpbmcgfCBudWxsOyBwcm9wczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCBudWxsOyBkZXNjcmlwdGlvbjogc3RyaW5nIHwgbnVsbDsgc3RhdHVzOiBzdHJpbmcgfCBudWxsOyBzb3VyY2VVcmw6IHN0cmluZyB8IG51bGwgfVxuXG5pbnRlcmZhY2UgQ29kZUNvbm5lY3REYXRhIHsgZmlsZTogeyBrZXk6IHN0cmluZyB9OyBtYXBwaW5nczogTWFwcGluZ1tdOyBjb21wb25lbnRzOiBOb3JtYWxpc2VkQ29tcG9uZW50W107IGRldlJlc291cmNlczogTm9ybWFsaXNlZERldlJlc291cmNlW10gfVxuXG5mdW5jdGlvbiBsb2cobWVzc2FnZTogc3RyaW5nLCB2ZXJib3NlOiBib29sZWFuKTogdm9pZCB7IGlmICh2ZXJib3NlKSBwcm9jZXNzLnN0ZGVyci53cml0ZShgWyR7VE9PTF9OQU1FfV0gJHttZXNzYWdlfVxcbmApIH1cbmZ1bmN0aW9uIHRvT3B0aW9uYWxTdHJpbmcodmFsdWU6IENsaUFyZ3Nbc3RyaW5nXSk6IHN0cmluZyB8IG51bGwgeyByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiB2YWx1ZS5sZW5ndGggPiAwID8gdmFsdWUgOiBudWxsIH1cbmZ1bmN0aW9uIGV4aXRXaXRoRW52ZWxvcGUoZW52ZWxvcGU6IFRvb2xFbnZlbG9wZTxUb29sSW5wdXQsIENvZGVDb25uZWN0RGF0YSB8IEVtcHR5RGF0YT4sIGVycm9yczogVG9vbEVycm9yW10gPSBbXSk6IG5ldmVyIHsgcHJvY2Vzcy5zdGRvdXQud3JpdGUoYCR7SlNPTi5zdHJpbmdpZnkoZW52ZWxvcGUsIG51bGwsIDIpfVxcbmApOyBwcm9jZXNzLmV4aXQoZ2V0RXhpdENvZGUoZXJyb3JzKSkgfVxuXG5hc3luYyBmdW5jdGlvbiByZWFkUmVwb0NvbmZpZygpOiBQcm9taXNlPFJlcG9Db25maWc+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBjb25maWdQYXRoID0gcGF0aC5yZXNvbHZlKCdjb25maWcvY29kZS1jb25uZWN0LW1hcC5qc29uJylcbiAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgcmVhZEZpbGUoY29uZmlnUGF0aCwgJ3V0ZjgnKVxuICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UoY29udGVudClcbiAgICBpZiAocGFyc2VkICYmIEFycmF5LmlzQXJyYXkocGFyc2VkLmNvbXBvbmVudHMpKSByZXR1cm4gcGFyc2VkXG4gICAgcmV0dXJuIHsgdmVyc2lvbjogJzAuMScsIGNvbXBvbmVudHM6IFtdIH1cbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHsgdmVyc2lvbjogJzAuMScsIGNvbXBvbmVudHM6IFtdIH1cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBtYWluKCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBhcmdzID0gcGFyc2VBcmdzKClcbiAgY29uc3QgdmVyYm9zZSA9IEJvb2xlYW4oYXJncy52ZXJib3NlID8/IGFyZ3MudilcbiAgY29uc3Qgc2NoZW1hVmVyc2lvbiA9IHRvT3B0aW9uYWxTdHJpbmcoYXJnc1snc2NoZW1hLXZlcnNpb24nXSkgPz8gdW5kZWZpbmVkXG5cbiAgY29uc3Qgd2FybmluZ3M6IHN0cmluZ1tdID0gW11cbiAgY29uc3QgZXJyb3JzOiBUb29sRXJyb3JbXSA9IFtdXG5cbiAgbGV0IHJlcG9Db25maWc6IFJlcG9Db25maWcgPSB7IHZlcnNpb246ICcwLjEnLCBjb21wb25lbnRzOiBbXSB9XG4gIHRyeSB7IHJlcG9Db25maWcgPSBhd2FpdCByZWFkUmVwb0NvbmZpZygpIH0gY2F0Y2ggKGVycm9yKSB7IHdhcm5pbmdzLnB1c2goZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpKSB9XG5cbiAgY29uc3QgdG9rZW4gPSBwcm9jZXNzLmVudi5GSUdNQV9BQ0NFU1NfVE9LRU5cbiAgaWYgKCF0b2tlbiB8fCAhdG9rZW4udHJpbSgpKSB7XG4gICAgZXJyb3JzLnB1c2goY3JlYXRlRXJyb3IoJ0ZJR01BX0FVVEgnLCAnRklHTUFfQUNDRVNTX1RPS0VOIGlzIHJlcXVpcmVkIGJ1dCB3YXMgbm90IHByb3ZpZGVkLicpKVxuICAgIGNvbnN0IGVudmVsb3BlID0gY3JlYXRlRW52ZWxvcGU8VG9vbElucHV0LCBFbXB0eURhdGE+KHsgdG9vbDogVE9PTF9OQU1FLCBpbnB1dDogeyBmaWxlS2V5OiBudWxsLCBub2RlSWQ6IG51bGwgfSwgd2FybmluZ3MsIGVycm9ycywgc2NoZW1hVmVyc2lvbiwgZGF0YToge30gYXMgRW1wdHlEYXRhIH0pXG4gICAgZXhpdFdpdGhFbnZlbG9wZShlbnZlbG9wZSwgZXJyb3JzKVxuICB9XG5cbiAgY29uc3QgdXJsSW5wdXQgPSB0b09wdGlvbmFsU3RyaW5nKGFyZ3MudXJsKSA/PyB0b09wdGlvbmFsU3RyaW5nKGFyZ3MudSlcbiAgbGV0IGZpbGVLZXkgPSB0b09wdGlvbmFsU3RyaW5nKGFyZ3NbJ2ZpbGUta2V5J10pID8/IHVuZGVmaW5lZFxuICBjb25zdCBub2RlSWRJbnB1dCA9IGVuc3VyZU5vZGVJZCh0b09wdGlvbmFsU3RyaW5nKGFyZ3NbJ25vZGUtaWQnXSkpXG4gIGlmICh1cmxJbnB1dCkgeyBjb25zdCBwYXJzZWQgPSBwYXJzZUZpZ21hVXJsKHVybElucHV0KTsgZmlsZUtleSA9IGZpbGVLZXkgfHwgcGFyc2VkLmZpbGVLZXkgfHwgdW5kZWZpbmVkIH1cblxuICBjb25zdCBpbnB1dDogVG9vbElucHV0ID0geyBmaWxlS2V5OiBmaWxlS2V5ID8/IG51bGwsIG5vZGVJZDogbm9kZUlkSW5wdXQgPz8gbnVsbCB9XG4gIGlmICghZmlsZUtleSkgZXJyb3JzLnB1c2goY3JlYXRlRXJyb3IoJ0lOUFVUX0lOVkFMSUQnLCAnQSB2YWxpZCBGaWdtYSBmaWxlIGtleSBpcyByZXF1aXJlZCAoLS1maWxlLWtleSBvciAtLXVybCkuJykpXG4gIGlmIChlcnJvcnMubGVuZ3RoKSB7IGNvbnN0IGVudmVsb3BlID0gY3JlYXRlRW52ZWxvcGU8VG9vbElucHV0LCBFbXB0eURhdGE+KHsgdG9vbDogVE9PTF9OQU1FLCBpbnB1dCwgd2FybmluZ3MsIGVycm9ycywgZGF0YToge30gYXMgRW1wdHlEYXRhLCBzY2hlbWFWZXJzaW9uIH0pOyBleGl0V2l0aEVudmVsb3BlKGVudmVsb3BlLCBlcnJvcnMpIH1cblxuICBjb25zdCByZXNvbHZlZEZpbGVLZXkgPSBmaWxlS2V5IGFzIHN0cmluZ1xuXG4gIGxvZygnRmV0Y2hpbmcgZGV2IHJlc291cmNlcycsIHZlcmJvc2UpXG4gIGNvbnN0IGRldlJlc291cmNlc1Jlc3BvbnNlID0gYXdhaXQgZmlnbWFSZXF1ZXN0PERldlJlc291cmNlUGF5bG9hZD4oeyBwYXRoOiBgL3YxL2ZpbGVzLyR7cmVzb2x2ZWRGaWxlS2V5fS9kZXZyZXNvdXJjZXNgLCB0b2tlbiB9KVxuICBsb2coJ0ZldGNoaW5nIGNvbXBvbmVudHMnLCB2ZXJib3NlKVxuICBjb25zdCBjb21wb25lbnRzUmVzcG9uc2UgPSBhd2FpdCBmaWdtYVJlcXVlc3Q8Q29tcG9uZW50c1BheWxvYWQ+KHsgcGF0aDogYC92MS9maWxlcy8ke3Jlc29sdmVkRmlsZUtleX0vY29tcG9uZW50c2AsIHRva2VuIH0pXG5cbiAgaWYgKCFkZXZSZXNvdXJjZXNSZXNwb25zZS5vaykge1xuICAgIGVycm9ycy5wdXNoKGRldlJlc291cmNlc1Jlc3BvbnNlLmVycm9yID8/IGNyZWF0ZUVycm9yKCdJTlRFUk5BTCcsICdGYWlsZWQgdG8gZmV0Y2ggZGV2IHJlc291cmNlcy4nKSlcbiAgICBjb25zdCBlbnZlbG9wZSA9IGNyZWF0ZUVudmVsb3BlPFRvb2xJbnB1dCwgRW1wdHlEYXRhPih7IHRvb2w6IFRPT0xfTkFNRSwgaW5wdXQsIHdhcm5pbmdzLCBlcnJvcnMsIHJhdGVMaW1pdDogZGV2UmVzb3VyY2VzUmVzcG9uc2UucmF0ZUxpbWl0ID8/IHVuZGVmaW5lZCwgc2NoZW1hVmVyc2lvbiwgZGF0YToge30gYXMgRW1wdHlEYXRhIH0pXG4gICAgZXhpdFdpdGhFbnZlbG9wZShlbnZlbG9wZSwgZXJyb3JzKVxuICB9XG4gIGlmICghY29tcG9uZW50c1Jlc3BvbnNlLm9rKSB3YXJuaW5ncy5wdXNoKGNvbXBvbmVudHNSZXNwb25zZS5lcnJvcj8ubWVzc2FnZSA/PyAnRmFpbGVkIHRvIGZldGNoIGNvbXBvbmVudHMuJylcblxuICBjb25zdCBkZXZSZXNvdXJjZXMgPSBkZXZSZXNvdXJjZXNSZXNwb25zZS5kYXRhPy5kZXZfcmVzb3VyY2VzID8/IFtdXG4gIGNvbnN0IGNvbXBvbmVudHNNYXA6IFJlY29yZDxzdHJpbmcsIENvbXBvbmVudE1ldGE+ID0gY29tcG9uZW50c1Jlc3BvbnNlLm9rID8gY29tcG9uZW50c1Jlc3BvbnNlLmRhdGE/LmNvbXBvbmVudHMgPz8ge30gOiB7fVxuICBjb25zdCByZXBvTWFwcGluZ3MgPSByZXBvQ29uZmlnLmNvbXBvbmVudHMgPz8gW11cblxuICBjb25zdCBub3JtYWxpc2VkUmVzb3VyY2VzOiBOb3JtYWxpc2VkRGV2UmVzb3VyY2VbXSA9IGRldlJlc291cmNlcy5tYXAoKHJlc291cmNlOiBEZXZSZXNvdXJjZSkgPT4gKHtcbiAgICBpZDogcmVzb3VyY2UuaWQsXG4gICAgbmFtZTogcmVzb3VyY2UubmFtZSxcbiAgICBkZXNjcmlwdGlvbjogcmVzb3VyY2UuZGVzY3JpcHRpb24gPz8gbnVsbCxcbiAgICB1cmw6IHJlc291cmNlLnVybCA/PyBudWxsLFxuICAgIG5vZGVJZDogcmVzb3VyY2Uubm9kZV9pZCA/PyBudWxsLFxuICAgIGNvbXBvbmVudElkOiByZXNvdXJjZS5jb21wb25lbnRfaWQgPz8gbnVsbCxcbiAgICBmaWxlS2V5OiByZXNvdXJjZS5maWxlX2tleSA/PyByZXNvbHZlZEZpbGVLZXksXG4gICAgc3RhdHVzOiByZXNvdXJjZS5zdGF0dXMgPz8gbnVsbCxcbiAgICBjcmVhdGVkQXQ6IHJlc291cmNlLmNyZWF0ZWRfYXQgPz8gbnVsbCxcbiAgICB1cGRhdGVkQXQ6IHJlc291cmNlLnVwZGF0ZWRfYXQgPz8gbnVsbCxcbiAgfSkpXG5cbiAgY29uc3Qgbm9ybWFsaXNlZENvbXBvbmVudHM6IE5vcm1hbGlzZWRDb21wb25lbnRbXSA9IE9iamVjdC5lbnRyaWVzKGNvbXBvbmVudHNNYXApLm1hcCgoW2NvbXBvbmVudElkLCBjb21wb25lbnRdKSA9PiAoe1xuICAgIGlkOiBjb21wb25lbnRJZCxcbiAgICBrZXk6IGNvbXBvbmVudC5rZXksXG4gICAgbmFtZTogY29tcG9uZW50Lm5hbWUsXG4gICAgZGVzY3JpcHRpb246IGNvbXBvbmVudC5kZXNjcmlwdGlvbiA/PyBudWxsLFxuICAgIGZpbGVLZXk6IGNvbXBvbmVudC5maWxlX2tleSA/PyByZXNvbHZlZEZpbGVLZXksXG4gICAgbm9kZUlkOiBjb21wb25lbnQubm9kZV9pZCA/PyBudWxsLFxuICB9KSlcblxuICBjb25zdCBmaW5kUmVwb01hcHBpbmcgPSAobmFtZT86IHN0cmluZyB8IG51bGwpID0+IHtcbiAgICBpZiAoIW5hbWUpIHJldHVybiBudWxsXG4gICAgcmV0dXJuIHJlcG9NYXBwaW5ncy5maW5kKChtKSA9PiBtLm5hbWUgPT09IG5hbWUgfHwgbS5jb21wb25lbnQgPT09IG5hbWUpID8/IG51bGxcbiAgfVxuXG4gIGNvbnN0IG1hcHBpbmdzOiBNYXBwaW5nW10gPSBub3JtYWxpc2VkUmVzb3VyY2VzLm1hcCgocmVzb3VyY2UpID0+IHtcbiAgICBjb25zdCBjb21wb25lbnQgPSByZXNvdXJjZS5jb21wb25lbnRJZCA/IG5vcm1hbGlzZWRDb21wb25lbnRzLmZpbmQoKGVudHJ5KSA9PiBlbnRyeS5pZCA9PT0gcmVzb3VyY2UuY29tcG9uZW50SWQpIDogbnVsbFxuICAgIGNvbnN0IHJlcG9NYXBwaW5nID0gZmluZFJlcG9NYXBwaW5nKGNvbXBvbmVudD8ubmFtZSA/PyByZXNvdXJjZS5uYW1lKVxuICAgIGlmICghcmVwb01hcHBpbmcpIHtcbiAgICAgIHdhcm5pbmdzLnB1c2goYE5vZGUgJHtyZXNvdXJjZS5ub2RlSWQgPz8gY29tcG9uZW50Py5ub2RlSWQgPz8gJ3Vua25vd24nfSAoJHtyZXNvdXJjZS5uYW1lID8/IGNvbXBvbmVudD8ubmFtZSA/PyAndW5uYW1lZCd9KSBoYXMgbm8gbWFwcGluZyBpbiBjb25maWcvY29kZS1jb25uZWN0LW1hcC5qc29uLmApXG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBub2RlSWQ6IHJlc291cmNlLm5vZGVJZCA/PyBjb21wb25lbnQ/Lm5vZGVJZCA/PyBudWxsLFxuICAgICAgY29tcG9uZW50SWQ6IHJlc291cmNlLmNvbXBvbmVudElkID8/IGNvbXBvbmVudD8uaWQgPz8gbnVsbCxcbiAgICAgIGNvbXBvbmVudEtleTogY29tcG9uZW50Py5rZXkgPz8gbnVsbCxcbiAgICAgIGNvbXBvbmVudE5hbWU6IGNvbXBvbmVudD8ubmFtZSA/PyByZXNvdXJjZS5uYW1lID8/IG51bGwsXG4gICAgICByZXBvQ29tcG9uZW50OiByZXBvTWFwcGluZz8uY29tcG9uZW50ID8/IG51bGwsXG4gICAgICByZXBvUGF0aDogcmVwb01hcHBpbmc/LnBhdGggPz8gbnVsbCxcbiAgICAgIHByb3BzOiByZXBvTWFwcGluZz8ucHJvcHMgPz8gbnVsbCxcbiAgICAgIGRlc2NyaXB0aW9uOiBjb21wb25lbnQ/LmRlc2NyaXB0aW9uID8/IHJlc291cmNlLmRlc2NyaXB0aW9uID8/IG51bGwsXG4gICAgICBzdGF0dXM6IHJlc291cmNlLnN0YXR1cyA/PyBudWxsLFxuICAgICAgc291cmNlVXJsOiByZXNvdXJjZS51cmwgPz8gbnVsbCxcbiAgICB9XG4gIH0pXG5cbiAgY29uc3QgZGF0YTogQ29kZUNvbm5lY3REYXRhID0geyBmaWxlOiB7IGtleTogcmVzb2x2ZWRGaWxlS2V5IH0sIG1hcHBpbmdzLCBjb21wb25lbnRzOiBub3JtYWxpc2VkQ29tcG9uZW50cywgZGV2UmVzb3VyY2VzOiBub3JtYWxpc2VkUmVzb3VyY2VzIH1cblxuICBjb25zdCBlbnZlbG9wZSA9IGNyZWF0ZUVudmVsb3BlPFRvb2xJbnB1dCwgQ29kZUNvbm5lY3REYXRhPih7IHRvb2w6IFRPT0xfTkFNRSwgaW5wdXQsIGRhdGEsIHdhcm5pbmdzLCBlcnJvcnMsIHJhdGVMaW1pdDogZGV2UmVzb3VyY2VzUmVzcG9uc2UucmF0ZUxpbWl0ID8/IHVuZGVmaW5lZCwgc2NoZW1hVmVyc2lvbiB9KVxuICBwcm9jZXNzLnN0ZG91dC53cml0ZShgJHtKU09OLnN0cmluZ2lmeShlbnZlbG9wZSwgbnVsbCwgMil9XFxuYClcbiAgcHJvY2Vzcy5leGl0KGdldEV4aXRDb2RlKGVycm9ycykpXG59XG5cbm1haW4oKS5jYXRjaCgoZXJyb3I6IHVua25vd24pID0+IHtcbiAgY29uc3QgbWVzc2FnZSA9IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogJ1Vua25vd24gZXJyb3InXG4gIGNvbnN0IGVudmVsb3BlID0gY3JlYXRlRW52ZWxvcGU8VG9vbElucHV0LCBFbXB0eURhdGE+KHsgdG9vbDogVE9PTF9OQU1FLCBpbnB1dDogeyBmaWxlS2V5OiBudWxsLCBub2RlSWQ6IG51bGwgfSwgZXJyb3JzOiBbY3JlYXRlRXJyb3IoJ0lOVEVSTkFMJywgbWVzc2FnZSwgeyBzdGFjazogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLnN0YWNrIDogdW5kZWZpbmVkIH0pXSwgZGF0YToge30gYXMgRW1wdHlEYXRhIH0pXG4gIHByb2Nlc3Muc3Rkb3V0LndyaXRlKGAke0pTT04uc3RyaW5naWZ5KGVudmVsb3BlLCBudWxsLCAyKX1cXG5gKVxuICBwcm9jZXNzLmV4aXQoMylcbn0pXG5cbiIsICJleHBvcnQgdHlwZSBDbGlBcmdWYWx1ZSA9IHN0cmluZyB8IGJvb2xlYW47XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xpQXJncyB7XG4gIF86IHN0cmluZ1tdO1xuICBba2V5OiBzdHJpbmddOiBDbGlBcmdWYWx1ZSB8IHN0cmluZ1tdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VBcmdzKGFyZ3Y6IHN0cmluZ1tdID0gcHJvY2Vzcy5hcmd2LnNsaWNlKDIpKTogQ2xpQXJncyB7XG4gIGNvbnN0IGFyZ3M6IENsaUFyZ3MgPSB7IF86IFtdIH07XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcmd2Lmxlbmd0aDsgaSArPSAxKSB7XG4gICAgY29uc3QgYXJnID0gYXJndltpXTtcblxuICAgIGlmICghYXJnLnN0YXJ0c1dpdGgoJy0nKSB8fCBhcmcgPT09ICctJykge1xuICAgICAgYXJncy5fLnB1c2goYXJnKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmIChhcmcgPT09ICctLScpIHtcbiAgICAgIGNvbnN0IHJlbWFpbmluZyA9IGFyZ3Yuc2xpY2UoaSArIDEpO1xuICAgICAgYXJncy5fLnB1c2goLi4ucmVtYWluaW5nKTtcbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGNvbnN0IFtyYXdLZXksIGlubGluZVZhbHVlXSA9IGFyZy5zcGxpdCgnPScsIDIpO1xuICAgIGNvbnN0IG5vcm1hbGlzZWRLZXkgPSByYXdLZXkucmVwbGFjZSgvXi0rLywgJycpO1xuXG4gICAgbGV0IHZhbHVlOiBDbGlBcmdWYWx1ZTtcbiAgICBpZiAoaW5saW5lVmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdmFsdWUgPSBpbmxpbmVWYWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgbmV4dCA9IGFyZ3ZbaSArIDFdO1xuICAgICAgaWYgKG5leHQgIT09IHVuZGVmaW5lZCAmJiAhbmV4dC5zdGFydHNXaXRoKCctJykpIHtcbiAgICAgICAgdmFsdWUgPSBuZXh0O1xuICAgICAgICBpICs9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YWx1ZSA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgYXJnc1tub3JtYWxpc2VkS2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgcmV0dXJuIGFyZ3M7XG59XG5cbiIsICJjb25zdCBGSUxFX0tFWV9SRUdFWCA9IC9maWdtYVxcLmNvbVxcLyg/OmZpbGV8ZGVzaWduKVxcLyhbQS1aYS16MC05XSspXFwvL2k7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFyc2VkRmlnbWFVcmwge1xuICBmaWxlS2V5OiBzdHJpbmcgfCBudWxsO1xuICBub2RlSWQ6IHN0cmluZyB8IG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUZpZ21hVXJsKGlucHV0OiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogUGFyc2VkRmlnbWFVcmwge1xuICBpZiAoIWlucHV0KSByZXR1cm4geyBmaWxlS2V5OiBudWxsLCBub2RlSWQ6IG51bGwgfTtcbiAgdHJ5IHtcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKGlucHV0KTtcbiAgICBjb25zdCBtYXRjaCA9IHVybC5ocmVmLm1hdGNoKEZJTEVfS0VZX1JFR0VYKTtcbiAgICBjb25zdCBmaWxlS2V5ID0gbWF0Y2ggPyBtYXRjaFsxXSA6IG51bGw7XG4gICAgY29uc3Qgbm9kZVBhcmFtID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ25vZGUtaWQnKTtcbiAgICBjb25zdCBub2RlSWQgPSBub2RlUGFyYW0gPyBlbnN1cmVOb2RlSWQobm9kZVBhcmFtKSA6IG51bGw7XG4gICAgcmV0dXJuIHsgZmlsZUtleSwgbm9kZUlkIH07XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB7IGZpbGVLZXk6IG51bGwsIG5vZGVJZDogbnVsbCB9O1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVOb2RlSWQodmFsdWU6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCBudWxsIHtcbiAgaWYgKCF2YWx1ZSkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IGRlY29kZWQgPSBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpO1xuICBpZiAoZGVjb2RlZC5pbmNsdWRlcygnOicpKSByZXR1cm4gZGVjb2RlZDtcbiAgaWYgKC9eWzAtOV0rLVswLTldKyQvLnRlc3QoZGVjb2RlZCkpIHtcbiAgICBjb25zdCBbbGVmdCwgcmlnaHRdID0gZGVjb2RlZC5zcGxpdCgnLScsIDIpO1xuICAgIHJldHVybiBgJHtsZWZ0fToke3JpZ2h0fWA7XG4gIH1cbiAgcmV0dXJuIGRlY29kZWQ7XG59XG5cbiIsICJleHBvcnQgZGVmYXVsdCB7XG4gIHNjaGVtYVZlcnNpb246ICcxLjAuMCcsXG4gIHNvdXJjZTogJ2FnZW50aWMtY29kaW5nLXRlbXBsYXRlcy9maWdtYS10b29scycsXG4gIGh0dHA6IHtcbiAgICBtYXhBdHRlbXB0czogNSxcbiAgICBpbml0aWFsRGVsYXlNczogMjUwLFxuICB9LFxufSBhcyBjb25zdDtcblxuIiwgImltcG9ydCBjb25maWcgZnJvbSAnLi9jb25maWcudHMnO1xuaW1wb3J0IHR5cGUgeyBUb29sRXJyb3IgfSBmcm9tICcuL2Vycm9ycy50cyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmF0ZUxpbWl0TWV0YSB7XG4gIHJlbWFpbmluZzogbnVtYmVyIHwgbnVsbDtcbiAgcmVzZXRBdDogc3RyaW5nIHwgbnVsbDtcbiAgYXR0ZW1wdHM6IG51bWJlcjtcbiAgbGFzdFdhaXRNczogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRvb2xFbnZlbG9wZTxcbiAgVElucHV0IGV4dGVuZHMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgVERhdGEgPSB1bmtub3duXG4+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/Lm1lc3NhZ2UgPz8gJ1VuZXhwZWN0ZWQgZXJyb3IgZnJvbSBGaWdtYSBBUEkuJywgeyBzdGF0dXMgfSksIHN0YXR1cywgcmF0ZUxpbWl0IH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG9rOiBmYWxzZSxcbiAgICBlcnJvcjogY3JlYXRlRXJyb3IoJ05FVFdPUksnLCAnVW5hYmxlIHRvIHJlYWNoIEZpZ21hIEFQSS4nKSxcbiAgICBzdGF0dXM6IG51bGwsXG4gICAgcmF0ZUxpbWl0OiB7IHJlbWFpbmluZzogbnVsbCwgcmVzZXRBdDogbnVsbCwgYXR0ZW1wdHM6IG1heEF0dGVtcHRzLCBsYXN0V2FpdE1zIH0sXG4gIH07XG59XG5cbiJdLAogICJtYXBwaW5ncyI6ICI7OztBQUVBLFNBQVMsZ0JBQWdCO0FBQ3pCLE9BQU8sVUFBVTs7O0FDSVYsU0FBUyxVQUFVLE9BQWlCLFFBQVEsS0FBSyxNQUFNLENBQUMsR0FBWTtBQUN6RSxRQUFNLE9BQWdCLEVBQUUsR0FBRyxDQUFDLEVBQUU7QUFFOUIsV0FBUyxJQUFJLEdBQUcsSUFBSSxLQUFLLFFBQVEsS0FBSyxHQUFHO0FBQ3ZDLFVBQU0sTUFBTSxLQUFLLENBQUM7QUFFbEIsUUFBSSxDQUFDLElBQUksV0FBVyxHQUFHLEtBQUssUUFBUSxLQUFLO0FBQ3ZDLFdBQUssRUFBRSxLQUFLLEdBQUc7QUFDZjtBQUFBLElBQ0Y7QUFFQSxRQUFJLFFBQVEsTUFBTTtBQUNoQixZQUFNLFlBQVksS0FBSyxNQUFNLElBQUksQ0FBQztBQUNsQyxXQUFLLEVBQUUsS0FBSyxHQUFHLFNBQVM7QUFDeEI7QUFBQSxJQUNGO0FBRUEsVUFBTSxDQUFDLFFBQVEsV0FBVyxJQUFJLElBQUksTUFBTSxLQUFLLENBQUM7QUFDOUMsVUFBTSxnQkFBZ0IsT0FBTyxRQUFRLE9BQU8sRUFBRTtBQUU5QyxRQUFJO0FBQ0osUUFBSSxnQkFBZ0IsUUFBVztBQUM3QixjQUFRO0FBQUEsSUFDVixPQUFPO0FBQ0wsWUFBTSxPQUFPLEtBQUss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