UNPKG

llmverify

Version:

AI Output Verification Toolkit — Local-first LLM safety, hallucination detection, PII redaction, prompt injection defense, and runtime monitoring. Zero telemetry. OWASP LLM Top 10 aligned.

224 lines (215 loc) 23.4 kB
"use strict"; /** * Badge Generator and Verification * * Generate "Built with llmverify" badges for verified applications * * @module badge/generator */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.generateBadgeSignature = generateBadgeSignature; exports.verifyBadgeSignature = verifyBadgeSignature; exports.generateBadgeMarkdown = generateBadgeMarkdown; exports.generateBadgeHTML = generateBadgeHTML; exports.extractBadgeVerification = extractBadgeVerification; exports.generateBadgeForProject = generateBadgeForProject; exports.saveBadgeToFile = saveBadgeToFile; const crypto = __importStar(require("crypto")); const fs = __importStar(require("fs")); /** * Generate badge verification signature */ function generateBadgeSignature(config) { const data = `${config.projectName}:${config.verifiedDate}:${config.version}`; return crypto.createHash('sha256').update(data).digest('hex').substring(0, 16); } /** * Verify badge signature */ function verifyBadgeSignature(projectName, verifiedDate, version, signature) { const expectedSignature = generateBadgeSignature({ projectName, verifiedDate, version }); return signature === expectedSignature; } /** * Generate badge markdown */ function generateBadgeMarkdown(config) { const signature = generateBadgeSignature(config); const badgeUrl = config.projectUrl ? `https://img.shields.io/badge/Built_with-llmverify-blue?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cGF0aCBkPSJNMTIgMkw0IDZWMTJDNCAyMC41IDEyIDIyIDEyIDIyQzEyIDIyIDIwIDIwLjUgMjAgMTJWNkwxMiAyWiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KICA8cGF0aCBkPSJNOSAxMkwxMSAxNEwxNSAxMCIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+` : 'https://img.shields.io/badge/Built_with-llmverify-blue'; const linkUrl = config.projectUrl || 'https://github.com/subodhkc/llmverify-npm'; return `[![Built with llmverify](${badgeUrl})](${linkUrl}) <!-- llmverify badge verification --> <!-- project: ${config.projectName} --> <!-- verified: ${config.verifiedDate} --> <!-- version: ${config.version} --> <!-- signature: ${signature} -->`; } /** * Generate badge HTML */ function generateBadgeHTML(config) { const signature = generateBadgeSignature(config); const linkUrl = config.projectUrl || 'https://github.com/subodhkc/llmverify-npm'; return `<a href="${linkUrl}" target="_blank" rel="noopener noreferrer"> <img src="https://img.shields.io/badge/Built_with-llmverify-blue" alt="Built with llmverify" /> </a> <!-- llmverify badge verification --> <!-- project: ${config.projectName} --> <!-- verified: ${config.verifiedDate} --> <!-- version: ${config.version} --> <!-- signature: ${signature} -->`; } /** * Extract badge verification from markdown/HTML */ function extractBadgeVerification(content) { const projectMatch = content.match(/<!-- project: (.+?) -->/); const verifiedMatch = content.match(/<!-- verified: (.+?) -->/); const versionMatch = content.match(/<!-- version: (.+?) -->/); const signatureMatch = content.match(/<!-- signature: (.+?) -->/); if (!projectMatch || !verifiedMatch || !versionMatch || !signatureMatch) { return null; } const projectName = projectMatch[1]; const verifiedDate = verifiedMatch[1]; const version = versionMatch[1]; const signature = signatureMatch[1]; const valid = verifyBadgeSignature(projectName, verifiedDate, version, signature); return { projectName, verifiedDate, version, signature, valid }; } /** * Validate badge generation request */ function validateBadgeRequest(projectName, projectUrl) { // Validate project name if (!projectName || projectName.trim().length === 0) { throw new Error('Project name is required'); } if (projectName.length > 100) { throw new Error('Project name must be less than 100 characters'); } // Prevent malicious names const maliciousPatterns = [ /<script/i, /javascript:/i, /on\w+=/i, /<iframe/i, /eval\(/i ]; if (maliciousPatterns.some(pattern => pattern.test(projectName))) { throw new Error('Project name contains invalid characters'); } // Validate URL if provided if (projectUrl) { try { const url = new URL(projectUrl); if (!['http:', 'https:'].includes(url.protocol)) { throw new Error('URL must use http or https protocol'); } } catch (error) { if (error.message === 'URL must use http or https protocol') { throw error; } throw new Error('Invalid project URL'); } } // Rate limiting check (simple in-memory) // Only enforce in production, not in tests if (process.env.NODE_ENV !== 'test') { const now = Date.now(); const key = `badge:${projectName}`; if (typeof global !== 'undefined') { const cache = global.__badgeCache || {}; const lastGenerated = cache[key]; if (lastGenerated && now - lastGenerated < 60000) { throw new Error('Badge generation rate limit exceeded. Please wait 1 minute.'); } cache[key] = now; global.__badgeCache = cache; } } } /** * CLI helper to generate badge */ function generateBadgeForProject(projectName, projectUrl, version) { // Validate request validateBadgeRequest(projectName, projectUrl); const config = { projectName: projectName.trim(), projectUrl, verifiedDate: new Date().toISOString().split('T')[0], version: version || require('../../package.json').version }; const signature = generateBadgeSignature(config); const markdown = generateBadgeMarkdown(config); const html = generateBadgeHTML(config); return { markdown, html, signature }; } /** * Save badge to file */ function saveBadgeToFile(outputPath, projectName, projectUrl) { const { markdown, html } = generateBadgeForProject(projectName, projectUrl); const content = `# llmverify Badge ## Markdown \`\`\`markdown ${markdown} \`\`\` ## HTML \`\`\`html ${html} \`\`\` ## Usage Copy the markdown or HTML code above and paste it into your README.md or website. The badge verifies that your project uses llmverify for AI output verification. `; fs.writeFileSync(outputPath, content, 'utf-8'); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2JhZGdlL2dlbmVyYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQThCSCx3REFHQztBQUtELG9EQVlDO0FBS0Qsc0RBZ0JDO0FBS0QsOENBYUM7QUFLRCw0REF3QkM7QUFrRUQsMERBb0JDO0FBS0QsMENBNkJDO0FBNU9ELCtDQUFpQztBQUNqQyx1Q0FBeUI7QUF3QnpCOztHQUVHO0FBQ0gsU0FBZ0Isc0JBQXNCLENBQUMsTUFBbUI7SUFDeEQsTUFBTSxJQUFJLEdBQUcsR0FBRyxNQUFNLENBQUMsV0FBVyxJQUFJLE1BQU0sQ0FBQyxZQUFZLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQzlFLE9BQU8sTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDakYsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0Isb0JBQW9CLENBQ2xDLFdBQW1CLEVBQ25CLFlBQW9CLEVBQ3BCLE9BQWUsRUFDZixTQUFpQjtJQUVqQixNQUFNLGlCQUFpQixHQUFHLHNCQUFzQixDQUFDO1FBQy9DLFdBQVc7UUFDWCxZQUFZO1FBQ1osT0FBTztLQUNSLENBQUMsQ0FBQztJQUNILE9BQU8sU0FBUyxLQUFLLGlCQUFpQixDQUFDO0FBQ3pDLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLHFCQUFxQixDQUFDLE1BQW1CO0lBQ3ZELE1BQU0sU0FBUyxHQUFHLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRWpELE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxVQUFVO1FBQ2hDLENBQUMsQ0FBQyxna0JBQWdrQjtR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QWdCLHVCQUF1QixDQUNyQyxXQUFtQixFQUNuQixVQUFtQixFQUNuQixPQUFnQjtJQUVoQixtQkFBbUI7SUFDbkIsb0JBQW9CLENBQUMsV0FBVyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBRTlDLE1BQU0sTUFBTSxHQUFnQjtRQUMxQixXQUFXLEVBQUUsV0FBVyxDQUFDLElBQUksRUFBRTtRQUMvQixVQUFVO1FBQ1YsWUFBWSxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRCxPQUFPLEVBQUUsT0FBTyxJQUFJLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLE9BQU87S0FDMUQsQ0FBQztJQUVGLE1BQU0sU0FBUyxHQUFHLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2pELE1BQU0sUUFBUSxHQUFHLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9DLE1BQU0sSUFBSSxHQUFHLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRXZDLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDO0FBQ3ZDLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLGVBQWUsQ0FDN0IsVUFBa0IsRUFDbEIsV0FBbUIsRUFDbkIsVUFBbUI7SUFFbkIsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsR0FBRyx1QkFBdUIsQ0FBQyxXQUFXLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFFNUUsTUFBTSxPQUFPLEdBQUc7Ozs7O0VBS2hCLFFBQVE7Ozs7OztFQU1SLElBQUk7Ozs7Ozs7O0NBUUwsQ0FBQztJQUVBLEVBQUUsQ0FBQyxhQUFhLENBQUMsVUFBVSxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztBQUNqRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBCYWRnZSBHZW5lcmF0b3IgYW5kIFZlcmlmaWNhdGlvblxuICogXG4gKiBHZW5lcmF0ZSBcIkJ1aWx0IHdpdGggbGxtdmVyaWZ5XCIgYmFkZ2VzIGZvciB2ZXJpZmllZCBhcHBsaWNhdGlvbnNcbiAqIFxuICogQG1vZHVsZSBiYWRnZS9nZW5lcmF0b3JcbiAqL1xuXG5pbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSAnY3J5cHRvJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5cbi8qKlxuICogQmFkZ2UgY29uZmlndXJhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJhZGdlQ29uZmlnIHtcbiAgcHJvamVjdE5hbWU6IHN0cmluZztcbiAgcHJvamVjdFVybD86IHN0cmluZztcbiAgdmVyaWZpZWREYXRlOiBzdHJpbmc7XG4gIHZlcnNpb246IHN0cmluZztcbn1cblxuLyoqXG4gKiBCYWRnZSB2ZXJpZmljYXRpb24gZGF0YVxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJhZGdlVmVyaWZpY2F0aW9uIHtcbiAgcHJvamVjdE5hbWU6IHN0cmluZztcbiAgdmVyaWZpZWREYXRlOiBzdHJpbmc7XG4gIHZlcnNpb246IHN0cmluZztcbiAgc2lnbmF0dXJlOiBzdHJpbmc7XG4gIHZhbGlkOiBib29sZWFuO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlIGJhZGdlIHZlcmlmaWNhdGlvbiBzaWduYXR1cmVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlQmFkZ2VTaWduYXR1cmUoY29uZmlnOiBCYWRnZUNvbmZpZyk6IHN0cmluZyB7XG4gIGNvbnN0IGRhdGEgPSBgJHtjb25maWcucHJvamVjdE5hbWV9OiR7Y29uZmlnLnZlcmlmaWVkRGF0ZX06JHtjb25maWcudmVyc2lvbn1gO1xuICByZXR1cm4gY3J5cHRvLmNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShkYXRhKS5kaWdlc3QoJ2hleCcpLnN1YnN0cmluZygwLCAxNik7XG59XG5cbi8qKlxuICogVmVyaWZ5IGJhZGdlIHNpZ25hdHVyZVxuICovXG5leHBvcnQgZnVuY3Rpb24gdmVyaWZ5QmFkZ2VTaWduYXR1cmUoXG4gIHByb2plY3ROYW1lOiBzdHJpbmcsXG4gIHZlcmlmaWVkRGF0ZTogc3RyaW5nLFxuICB2ZXJzaW9uOiBzdHJpbmcsXG4gIHNpZ25hdHVyZTogc3RyaW5nXG4pOiBib29sZWFuIHtcbiAgY29uc3QgZXhwZWN0ZWRTaWduYXR1cmUgPSBnZW5lcmF0ZUJhZGdlU2lnbmF0dXJlKHtcbiAgICBwcm9qZWN0TmFtZSxcbiAgICB2ZXJpZmllZERhdGUsXG4gICAgdmVyc2lvblxuICB9KTtcbiAgcmV0dXJuIHNpZ25hdHVyZSA9PT0gZXhwZWN0ZWRTaWduYXR1cmU7XG59XG5cbi8qKlxuICogR2VuZXJhdGUgYmFkZ2UgbWFya2Rvd25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlQmFkZ2VNYXJrZG93bihjb25maWc6IEJhZGdlQ29uZmlnKTogc3RyaW5nIHtcbiAgY29uc3Qgc2lnbmF0dXJlID0gZ2VuZXJhdGVCYWRnZVNpZ25hdHVyZShjb25maWcpO1xuICBcbiAgY29uc3QgYmFkZ2VVcmwgPSBjb25maWcucHJvamVjdFVybCBcbiAgICA/IGBodHRwczovL2ltZy5zaGllbGRzLmlvL2JhZGdlL0J1aWx0X3dpdGgtbGxtdmVyaWZ5LWJsdWU/bG9nbz1kYXRhOmltYWdlL3N2Zyt4bWw7YmFzZTY0LFBITjJaeUIzYVdSMGFEMGlNalFpSUdobGFXZG9kRDBpTWpRaUlIWnBaWGRDYjNnOUlqQWdNQ0F5TkNBeU5DSWdabWxzYkQwaWJtOXVaU0lnZUcxc2JuTTlJbWgwZEhBNkx5OTNkM2N1ZHpNdWIzSm5Mekl3TURBdmMzWm5JajRLSUNBOGNHRjBhQ0JrUFNKTk1USWdNa3cwSURaV01USkROQ0F5TUM0MUlERXlJREl5SURFeUlESXlRekV5SURJeUlESXdJREl3TGpVZ01qQWdNVEpXTmt3eE1pQXlXaUlnYzNSeWIydGxQU0ozYUdsMFpTSWdjM1J5YjJ0bExYZHBaSFJvUFNJeUlpQnpkSEp2YTJVdGJHbHVaV05oY0QwaWNtOTFibVFpSUhOMGNtOXJaUzFzYVc1bGFtOXBiajBpY205MWJtUWlMejRLSUNBOGNHRjBhQ0JrUFNKTk9TQXhNa3d4TVNBeE5Fd3hOU0F4TUNJZ2MzUnliMnRsUFNKM2FHbDBaU0lnYzNSeWIydGxMWGRwWkhSb1BTSXlJaUJ6ZEhKdmEyVXRiR2x1WldOaGNEMGljbTkxYm1RaUlITjBjbTlyWlMxc2FXNWxhbTlwYmowaWNtOTFibVFpTHo0S1BDOXpkbWMrYFxuICAgIDogJ2h0dHBzOi8vaW1nLnNoaWVsZHMuaW8vYmFkZ2UvQnVpbHRfd2l0aC1sbG12ZXJpZnktYmx1ZSc7XG4gIFxuICBjb25zdCBsaW5rVXJsID0gY29uZmlnLnByb2plY3RVcmwgfHwgJ2h0dHBzOi8vZ2l0aHViLmNvbS9zdWJvZGhrYy9sbG12ZXJpZnktbnBtJztcbiAgXG4gIHJldHVybiBgWyFbQnVpbHQgd2l0aCBsbG12ZXJpZnldKCR7YmFkZ2VVcmx9KV0oJHtsaW5rVXJsfSlcblxuPCEtLSBsbG12ZXJpZnkgYmFkZ2UgdmVyaWZpY2F0aW9uIC0tPlxuPCEtLSBwcm9qZWN0OiAke2NvbmZpZy5wcm9qZWN0TmFtZX0gLS0+XG48IS0tIHZlcmlmaWVkOiAke2NvbmZpZy52ZXJpZmllZERhdGV9IC0tPlxuPCEtLSB2ZXJzaW9uOiAke2NvbmZpZy52ZXJzaW9ufSAtLT5cbjwhLS0gc2lnbmF0dXJlOiAke3NpZ25hdHVyZX0gLS0+YDtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZSBiYWRnZSBIVE1MXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZUJhZGdlSFRNTChjb25maWc6IEJhZGdlQ29uZmlnKTogc3RyaW5nIHtcbiAgY29uc3Qgc2lnbmF0dXJlID0gZ2VuZXJhdGVCYWRnZVNpZ25hdHVyZShjb25maWcpO1xuICBjb25zdCBsaW5rVXJsID0gY29uZmlnLnByb2plY3RVcmwgfHwgJ2h0dHBzOi8vZ2l0aHViLmNvbS9zdWJvZGhrYy9sbG12ZXJpZnktbnBtJztcbiAgXG4gIHJldHVybiBgPGEgaHJlZj1cIiR7bGlua1VybH1cIiB0YXJnZXQ9XCJfYmxhbmtcIiByZWw9XCJub29wZW5lciBub3JlZmVycmVyXCI+XG4gIDxpbWcgc3JjPVwiaHR0cHM6Ly9pbWcuc2hpZWxkcy5pby9iYWRnZS9CdWlsdF93aXRoLWxsbXZlcmlmeS1ibHVlXCIgYWx0PVwiQnVpbHQgd2l0aCBsbG12ZXJpZnlcIiAvPlxuPC9hPlxuXG48IS0tIGxsbXZlcmlmeSBiYWRnZSB2ZXJpZmljYXRpb24gLS0+XG48IS0tIHByb2plY3Q6ICR7Y29uZmlnLnByb2plY3ROYW1lfSAtLT5cbjwhLS0gdmVyaWZpZWQ6ICR7Y29uZmlnLnZlcmlmaWVkRGF0ZX0gLS0+XG48IS0tIHZlcnNpb246ICR7Y29uZmlnLnZlcnNpb259IC0tPlxuPCEtLSBzaWduYXR1cmU6ICR7c2lnbmF0dXJlfSAtLT5gO1xufVxuXG4vKipcbiAqIEV4dHJhY3QgYmFkZ2UgdmVyaWZpY2F0aW9uIGZyb20gbWFya2Rvd24vSFRNTFxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdEJhZGdlVmVyaWZpY2F0aW9uKGNvbnRlbnQ6IHN0cmluZyk6IEJhZGdlVmVyaWZpY2F0aW9uIHwgbnVsbCB7XG4gIGNvbnN0IHByb2plY3RNYXRjaCA9IGNvbnRlbnQubWF0Y2goLzwhLS0gcHJvamVjdDogKC4rPykgLS0+Lyk7XG4gIGNvbnN0IHZlcmlmaWVkTWF0Y2ggPSBjb250ZW50Lm1hdGNoKC88IS0tIHZlcmlmaWVkOiAoLis/KSAtLT4vKTtcbiAgY29uc3QgdmVyc2lvbk1hdGNoID0gY29udGVudC5tYXRjaCgvPCEtLSB2ZXJzaW9uOiAoLis/KSAtLT4vKTtcbiAgY29uc3Qgc2lnbmF0dXJlTWF0Y2ggPSBjb250ZW50Lm1hdGNoKC88IS0tIHNpZ25hdHVyZTogKC4rPykgLS0+Lyk7XG4gIFxuICBpZiAoIXByb2plY3RNYXRjaCB8fCAhdmVyaWZpZWRNYXRjaCB8fCAhdmVyc2lvbk1hdGNoIHx8ICFzaWduYXR1cmVNYXRjaCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIFxuICBjb25zdCBwcm9qZWN0TmFtZSA9IHByb2plY3RNYXRjaFsxXTtcbiAgY29uc3QgdmVyaWZpZWREYXRlID0gdmVyaWZpZWRNYXRjaFsxXTtcbiAgY29uc3QgdmVyc2lvbiA9IHZlcnNpb25NYXRjaFsxXTtcbiAgY29uc3Qgc2lnbmF0dXJlID0gc2lnbmF0dXJlTWF0Y2hbMV07XG4gIFxuICBjb25zdCB2YWxpZCA9IHZlcmlmeUJhZGdlU2lnbmF0dXJlKHByb2plY3ROYW1lLCB2ZXJpZmllZERhdGUsIHZlcnNpb24sIHNpZ25hdHVyZSk7XG4gIFxuICByZXR1cm4ge1xuICAgIHByb2plY3ROYW1lLFxuICAgIHZlcmlmaWVkRGF0ZSxcbiAgICB2ZXJzaW9uLFxuICAgIHNpZ25hdHVyZSxcbiAgICB2YWxpZFxuICB9O1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIGJhZGdlIGdlbmVyYXRpb24gcmVxdWVzdFxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZUJhZGdlUmVxdWVzdChwcm9qZWN0TmFtZTogc3RyaW5nLCBwcm9qZWN0VXJsPzogc3RyaW5nKTogdm9pZCB7XG4gIC8vIFZhbGlkYXRlIHByb2plY3QgbmFtZVxuICBpZiAoIXByb2plY3ROYW1lIHx8IHByb2plY3ROYW1lLnRyaW0oKS5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Byb2plY3QgbmFtZSBpcyByZXF1aXJlZCcpO1xuICB9XG4gIFxuICBpZiAocHJvamVjdE5hbWUubGVuZ3RoID4gMTAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQcm9qZWN0IG5hbWUgbXVzdCBiZSBsZXNzIHRoYW4gMTAwIGNoYXJhY3RlcnMnKTtcbiAgfVxuICBcbiAgLy8gUHJldmVudCBtYWxpY2lvdXMgbmFtZXNcbiAgY29uc3QgbWFsaWNpb3VzUGF0dGVybnMgPSBbXG4gICAgLzxzY3JpcHQvaSxcbiAgICAvamF2YXNjcmlwdDovaSxcbiAgICAvb25cXHcrPS9pLFxuICAgIC88aWZyYW1lL2ksXG4gICAgL2V2YWxcXCgvaVxuICBdO1xuICBcbiAgaWYgKG1hbGljaW91c1BhdHRlcm5zLnNvbWUocGF0dGVybiA9PiBwYXR0ZXJuLnRlc3QocHJvamVjdE5hbWUpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignUHJvamVjdCBuYW1lIGNvbnRhaW5zIGludmFsaWQgY2hhcmFjdGVycycpO1xuICB9XG4gIFxuICAvLyBWYWxpZGF0ZSBVUkwgaWYgcHJvdmlkZWRcbiAgaWYgKHByb2plY3RVcmwpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdXJsID0gbmV3IFVSTChwcm9qZWN0VXJsKTtcbiAgICAgIGlmICghWydodHRwOicsICdodHRwczonXS5pbmNsdWRlcyh1cmwucHJvdG9jb2wpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVVJMIG11c3QgdXNlIGh0dHAgb3IgaHR0cHMgcHJvdG9jb2wnKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBpZiAoZXJyb3IubWVzc2FnZSA9PT0gJ1VSTCBtdXN0IHVzZSBodHRwIG9yIGh0dHBzIHByb3RvY29sJykge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBwcm9qZWN0IFVSTCcpO1xuICAgIH1cbiAgfVxuICBcbiAgLy8gUmF0ZSBsaW1pdGluZyBjaGVjayAoc2ltcGxlIGluLW1lbW9yeSlcbiAgLy8gT25seSBlbmZvcmNlIGluIHByb2R1Y3Rpb24sIG5vdCBpbiB0ZXN0c1xuICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICd0ZXN0Jykge1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgY29uc3Qga2V5ID0gYGJhZGdlOiR7cHJvamVjdE5hbWV9YDtcbiAgICBcbiAgICBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGNvbnN0IGNhY2hlID0gKGdsb2JhbCBhcyBhbnkpLl9fYmFkZ2VDYWNoZSB8fCB7fTtcbiAgICAgIGNvbnN0IGxhc3RHZW5lcmF0ZWQgPSBjYWNoZVtrZXldO1xuICAgICAgXG4gICAgICBpZiAobGFzdEdlbmVyYXRlZCAmJiBub3cgLSBsYXN0R2VuZXJhdGVkIDwgNjAwMDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdCYWRnZSBnZW5lcmF0aW9uIHJhdGUgbGltaXQgZXhjZWVkZWQuIFBsZWFzZSB3YWl0IDEgbWludXRlLicpO1xuICAgICAgfVxuICAgICAgXG4gICAgICBjYWNoZVtrZXldID0gbm93O1xuICAgICAgKGdsb2JhbCBhcyBhbnkpLl9fYmFkZ2VDYWNoZSA9IGNhY2hlO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIENMSSBoZWxwZXIgdG8gZ2VuZXJhdGUgYmFkZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlQmFkZ2VGb3JQcm9qZWN0KFxuICBwcm9qZWN0TmFtZTogc3RyaW5nLFxuICBwcm9qZWN0VXJsPzogc3RyaW5nLFxuICB2ZXJzaW9uPzogc3RyaW5nXG4pOiB7IG1hcmtkb3duOiBzdHJpbmc7IGh0bWw6IHN0cmluZzsgc2lnbmF0dXJlOiBzdHJpbmcgfSB7XG4gIC8vIFZhbGlkYXRlIHJlcXVlc3RcbiAgdmFsaWRhdGVCYWRnZVJlcXVlc3QocHJvamVjdE5hbWUsIHByb2plY3RVcmwpO1xuICBcbiAgY29uc3QgY29uZmlnOiBCYWRnZUNvbmZpZyA9IHtcbiAgICBwcm9qZWN0TmFtZTogcHJvamVjdE5hbWUudHJpbSgpLFxuICAgIHByb2plY3RVcmwsXG4gICAgdmVyaWZpZWREYXRlOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkuc3BsaXQoJ1QnKVswXSxcbiAgICB2ZXJzaW9uOiB2ZXJzaW9uIHx8IHJlcXVpcmUoJy4uLy4uL3BhY2thZ2UuanNvbicpLnZlcnNpb25cbiAgfTtcbiAgXG4gIGNvbnN0IHNpZ25hdHVyZSA9IGdlbmVyYXRlQmFkZ2VTaWduYXR1cmUoY29uZmlnKTtcbiAgY29uc3QgbWFya2Rvd24gPSBnZW5lcmF0ZUJhZGdlTWFya2Rvd24oY29uZmlnKTtcbiAgY29uc3QgaHRtbCA9IGdlbmVyYXRlQmFkZ2VIVE1MKGNvbmZpZyk7XG4gIFxuICByZXR1cm4geyBtYXJrZG93biwgaHRtbCwgc2lnbmF0dXJlIH07XG59XG5cbi8qKlxuICogU2F2ZSBiYWRnZSB0byBmaWxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzYXZlQmFkZ2VUb0ZpbGUoXG4gIG91dHB1dFBhdGg6IHN0cmluZyxcbiAgcHJvamVjdE5hbWU6IHN0cmluZyxcbiAgcHJvamVjdFVybD86IHN0cmluZ1xuKTogdm9pZCB7XG4gIGNvbnN0IHsgbWFya2Rvd24sIGh0bWwgfSA9IGdlbmVyYXRlQmFkZ2VGb3JQcm9qZWN0KHByb2plY3ROYW1lLCBwcm9qZWN0VXJsKTtcbiAgXG4gIGNvbnN0IGNvbnRlbnQgPSBgIyBsbG12ZXJpZnkgQmFkZ2VcblxuIyMgTWFya2Rvd25cblxuXFxgXFxgXFxgbWFya2Rvd25cbiR7bWFya2Rvd259XG5cXGBcXGBcXGBcblxuIyMgSFRNTFxuXG5cXGBcXGBcXGBodG1sXG4ke2h0bWx9XG5cXGBcXGBcXGBcblxuIyMgVXNhZ2VcblxuQ29weSB0aGUgbWFya2Rvd24gb3IgSFRNTCBjb2RlIGFib3ZlIGFuZCBwYXN0ZSBpdCBpbnRvIHlvdXIgUkVBRE1FLm1kIG9yIHdlYnNpdGUuXG5cblRoZSBiYWRnZSB2ZXJpZmllcyB0aGF0IHlvdXIgcHJvamVjdCB1c2VzIGxsbXZlcmlmeSBmb3IgQUkgb3V0cHV0IHZlcmlmaWNhdGlvbi5cbmA7XG4gIFxuICBmcy53cml0ZUZpbGVTeW5jKG91dHB1dFBhdGgsIGNvbnRlbnQsICd1dGYtOCcpO1xufVxuIl19