UNPKG

simplr-tslint

Version:

A set of TSLint rules used in SimplrJS projects.

176 lines 30.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = require("path"); const ts = require("typescript"); const Lint = require("tslint"); const fs = require("fs"); class Rule extends Lint.Rules.AbstractRule { static resolveModuleFilename(moduleName) { return moduleName + this.moduleFilenameSuffix; } apply(sourceFile) { return this.applyWithWalker(new ImportModuleWalker(sourceFile, this.getOptions())); } static getComponentEntryFileFromCache(fileName) { return this.componentsEntryFilesCache[fileName]; } static setComponentEntryFileToCache(fileName, value) { this.componentsEntryFilesCache[fileName] = value; } } Rule.sep = "/"; Rule.searchModulePath = ["app", "components"].join(Rule.sep); Rule.searchModulePathSplitter = Rule.searchModulePath + Rule.sep; Rule.entryFailureString = "Components should be imported from an entry file."; Rule.insideRelativeFailureString = "A relative import should be used inside the components."; Rule.insideEntryFailureString = "An entry file import should not be used inside the components."; Rule.forbiddenReexportAllFailureString = "Forbidden 'export * from', use named re-exports."; Rule.moduleFilenameSuffix = "-components"; Rule.reexportPathRegex = /export[\s\S]*from[\s]*[\'\"](.*)[\'\"]/; Rule.reexportAllPathRegex = /export[\s\S]*\*/; Rule.componentsEntryFilesCache = {}; exports.Rule = Rule; class ImportModuleWalker extends Lint.RuleWalker { /** * Update import path with module entry file. */ importEntryFileFixer(start, length, prefix, moduleName, fullModuleName, quoteSymbol) { const resolvedImport = [ prefix + Rule.searchModulePath, moduleName, fullModuleName + quoteSymbol ].join(Rule.sep); return new Lint.Replacement(start, length, resolvedImport); } /** * Change path to relative. */ importWithRelativePathFixer(start, length, importFileName, sourceSplitPath, importSplitPath, quoteSymbol) { const sourcePath = sourceSplitPath.slice(0, -1).join(Rule.sep); const importPath = importSplitPath.slice(0, -1).join(Rule.sep); const relativePath = path.relative(sourcePath, importPath).split(path.sep); relativePath.push(importFileName); let relativePathString = relativePath.join(Rule.sep); if (relativePathString[0] === Rule.sep) { relativePathString = "." + relativePathString; } else if (relativePathString[0] !== ".") { relativePathString = `.${Rule.sep}${relativePathString}`; } const fixedPath = `${quoteSymbol}${relativePathString}${quoteSymbol}`; return new Lint.Replacement(start, length, fixedPath); } /** * Generate path details object from pathname. */ parsePathDetails(pathname, withQuotes = true) { const [prefix, suffix] = pathname.split(Rule.searchModulePathSplitter); const [moduleName, ...importSplitPath] = suffix.split(Rule.sep); if (withQuotes) { importSplitPath[importSplitPath.length - 1] = importSplitPath[importSplitPath.length - 1].slice(0, -1); } const [fileName] = importSplitPath.slice(-1); return { prefix: prefix, suffix: suffix, moduleName: moduleName, fullModuleName: Rule.resolveModuleFilename(moduleName), splitPath: importSplitPath, fileName: fileName, withQuotes: withQuotes }; } /** * Validate import line. */ startValidating(sourceFile, importFile, importStart, quote = "") { const sourceFileIsFromModule = sourceFile.indexOf(Rule.searchModulePath) > -1; const importFileIsFromModule = importFile.indexOf(Rule.searchModulePath) > -1; if (!sourceFileIsFromModule && !importFileIsFromModule) { return; } // Check if importing file is not from module if (!importFileIsFromModule) { // Check if source file is from module if (sourceFileIsFromModule) { const sourceDetails = this.parsePathDetails(sourceFile, false); const importFileName = importFile.split(Rule.sep).slice(-1)[0].slice(0, -1); const targetFileName = sourceDetails.fullModuleName; // Check if module itself doesn't import from entry file if (importFileName === targetFileName) { this.addFailureAt(importStart, importFile.length, Rule.insideEntryFailureString); } } return; } const importDetails = this.parsePathDetails(importFile, Boolean(quote)); if (sourceFileIsFromModule && importFileIsFromModule) { const sourceDetails = this.parsePathDetails(sourceFile, false); if (sourceDetails.moduleName === importDetails.moduleName) { const fix = this.importWithRelativePathFixer(importStart, importFile.length, importDetails.fileName, sourceDetails.splitPath, importDetails.splitPath, quote); this.addFailureAt(importStart, importFile.length, Rule.insideRelativeFailureString, fix); return; } } if (importFileIsFromModule && (importDetails.splitPath.length > 1 || importDetails.fullModuleName !== importDetails.fileName)) { const fromCache = Rule.getComponentEntryFileFromCache(importDetails.fullModuleName); let isComponentsWithEntry; if (fromCache == null) { isComponentsWithEntry = fs.existsSync(importDetails.fullModuleName); Rule.setComponentEntryFileToCache(importDetails.fullModuleName, isComponentsWithEntry); } else { isComponentsWithEntry = fromCache; } if (isComponentsWithEntry) { const fix = this.importEntryFileFixer(importStart, importFile.length, importDetails.prefix, importDetails.moduleName, importDetails.fullModuleName, quote); this.addFailureAt(importStart, importFile.length, Rule.entryFailureString, fix); } return; } } startValidatingReExportAll(fullText, sourceFile, node) { const sourceFileIsFromModule = sourceFile.indexOf(Rule.searchModulePath) > -1; if (sourceFileIsFromModule && Rule.reexportAllPathRegex.test(fullText)) { this.addFailureAtNode(node, Rule.forbiddenReexportAllFailureString); } } /** * Visit on import declaration found. */ visitImportDeclaration(node) { const sourceFile = node.getSourceFile().fileName; const importFile = node.moduleSpecifier.getText(); const importStart = node.moduleSpecifier.getStart(); const quoteSymbol = importFile[0]; this.startValidating(sourceFile, importFile, importStart, quoteSymbol); super.visitImportDeclaration(node); } /** * Visit on any source file. */ visitSourceFile(node) { const fullText = node.getFullText(); const sourceFile = node.fileName; if (node.statements.length > 0) { node.statements .filter(x => x.kind === ts.SyntaxKind.ExportDeclaration && x.getFullText().indexOf("from") > -1) .forEach(statement => { const text = statement.getFullText(); const regexResult = Rule.reexportPathRegex.exec(text); if (regexResult == null) { return; } const importFile = regexResult[1]; if (importFile == null) { return; } this.startValidatingReExportAll(text, sourceFile, statement); const importStart = fullText.indexOf(importFile); this.startValidating(sourceFile, importFile, importStart); }); } super.visitSourceFile(node); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1wb3J0Q29tcG9uZW50c1J1bGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW1wb3J0Q29tcG9uZW50c1J1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw2QkFBNkI7QUFDN0IsaUNBQWlDO0FBQ2pDLCtCQUErQjtBQUMvQix5QkFBeUI7QUFZekIsVUFBa0IsU0FBUSxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVk7SUFnQnRDLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxVQUFrQjtRQUNsRCxPQUFPLFVBQVUsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUM7SUFDbEQsQ0FBQztJQUVNLEtBQUssQ0FBQyxVQUF5QjtRQUNsQyxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN2RixDQUFDO0lBSU0sTUFBTSxDQUFDLDhCQUE4QixDQUFDLFFBQWdCO1FBQ3pELE9BQU8sSUFBSSxDQUFDLHlCQUF5QixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFFTSxNQUFNLENBQUMsNEJBQTRCLENBQUMsUUFBZ0IsRUFBRSxLQUFjO1FBQ3ZFLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxRQUFRLENBQUMsR0FBRyxLQUFLLENBQUM7SUFDckQsQ0FBQzs7QUEvQnNCLFFBQUcsR0FBVyxHQUFHLENBQUM7QUFFbEIscUJBQWdCLEdBQVcsQ0FBQyxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNoRSw2QkFBd0IsR0FBVyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQztBQUVwRSx1QkFBa0IsR0FBVyxtREFBbUQsQ0FBQztBQUNqRixnQ0FBMkIsR0FBVyx5REFBeUQsQ0FBQztBQUNoRyw2QkFBd0IsR0FBVyxnRUFBZ0UsQ0FBQztB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Z0JBRTdELE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ2pELElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQztZQUM5RCxDQUFDLENBQUMsQ0FBQztTQUNWO1FBRUQsS0FBSyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoQyxDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XHJcbmltcG9ydCAqIGFzIHRzIGZyb20gXCJ0eXBlc2NyaXB0XCI7XHJcbmltcG9ydCAqIGFzIExpbnQgZnJvbSBcInRzbGludFwiO1xyXG5pbXBvcnQgKiBhcyBmcyBmcm9tIFwiZnNcIjtcclxuXHJcbmludGVyZmFjZSBQYXRoRGV0YWlscyB7XHJcbiAgICBwcmVmaXg6IHN0cmluZztcclxuICAgIHN1ZmZpeDogc3RyaW5nO1xyXG4gICAgbW9kdWxlTmFtZTogc3RyaW5nO1xyXG4gICAgZnVsbE1vZHVsZU5hbWU6IHN0cmluZztcclxuICAgIGZpbGVOYW1lOiBzdHJpbmc7XHJcbiAgICBzcGxpdFBhdGg6IHN0cmluZ1tdO1xyXG4gICAgd2l0aFF1b3RlczogYm9vbGVhbjtcclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIFJ1bGUgZXh0ZW5kcyBMaW50LlJ1bGVzLkFic3RyYWN0UnVsZSB7XHJcbiAgICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IHNlcDogc3RyaW5nID0gXCIvXCI7XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBzZWFyY2hNb2R1bGVQYXRoOiBzdHJpbmcgPSBbXCJhcHBcIiwgXCJjb21wb25lbnRzXCJdLmpvaW4oUnVsZS5zZXApO1xyXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBzZWFyY2hNb2R1bGVQYXRoU3BsaXR0ZXI6IHN0cmluZyA9IFJ1bGUuc2VhcmNoTW9kdWxlUGF0aCArIFJ1bGUuc2VwO1xyXG5cclxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgZW50cnlGYWlsdXJlU3RyaW5nOiBzdHJpbmcgPSBcIkNvbXBvbmVudHMgc2hvdWxkIGJlIGltcG9ydGVkIGZyb20gYW4gZW50cnkgZmlsZS5cIjtcclxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgaW5zaWRlUmVsYXRpdmVGYWlsdXJlU3RyaW5nOiBzdHJpbmcgPSBcIkEgcmVsYXRpdmUgaW1wb3J0IHNob3VsZCBiZSB1c2VkIGluc2lkZSB0aGUgY29tcG9uZW50cy5cIjtcclxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgaW5zaWRlRW50cnlGYWlsdXJlU3RyaW5nOiBzdHJpbmcgPSBcIkFuIGVudHJ5IGZpbGUgaW1wb3J0IHNob3VsZCBub3QgYmUgdXNlZCBpbnNpZGUgdGhlIGNvbXBvbmVudHMuXCI7XHJcbiAgICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IGZvcmJpZGRlblJlZXhwb3J0QWxsRmFpbHVyZVN0cmluZzogc3RyaW5nID0gXCJGb3JiaWRkZW4gJ2V4cG9ydCAqIGZyb20nLCB1c2UgbmFtZWQgcmUtZXhwb3J0cy5cIjtcclxuXHJcbiAgICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IG1vZHVsZUZpbGVuYW1lU3VmZml4OiBzdHJpbmcgPSBcIi1jb21wb25lbnRzXCI7XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSByZWV4cG9ydFBhdGhSZWdleDogUmVnRXhwID0gL2V4cG9ydFtcXHNcXFNdKmZyb21bXFxzXSpbXFwnXFxcIl0oLiopW1xcJ1xcXCJdLztcclxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgcmVleHBvcnRBbGxQYXRoUmVnZXg6IFJlZ0V4cCA9IC9leHBvcnRbXFxzXFxTXSpcXCovO1xyXG5cclxuICAgIHB1YmxpYyBzdGF0aWMgcmVzb2x2ZU1vZHVsZUZpbGVuYW1lKG1vZHVsZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIG1vZHVsZU5hbWUgKyB0aGlzLm1vZHVsZUZpbGVuYW1lU3VmZml4O1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBhcHBseShzb3VyY2VGaWxlOiB0cy5Tb3VyY2VGaWxlKTogTGludC5SdWxlRmFpbHVyZVtdIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5hcHBseVdpdGhXYWxrZXIobmV3IEltcG9ydE1vZHVsZVdhbGtlcihzb3VyY2VGaWxlLCB0aGlzLmdldE9wdGlvbnMoKSkpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIGNvbXBvbmVudHNFbnRyeUZpbGVzQ2FjaGU6IHsgW2ZpbGVOYW1lOiBzdHJpbmddOiBib29sZWFuIH0gPSB7fTtcclxuXHJcbiAgICBwdWJsaWMgc3RhdGljIGdldENvbXBvbmVudEVudHJ5RmlsZUZyb21DYWNoZShmaWxlTmFtZTogc3RyaW5nKTogdW5kZWZpbmVkIHwgYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY29tcG9uZW50c0VudHJ5RmlsZXNDYWNoZVtmaWxlTmFtZV07XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyBzZXRDb21wb25lbnRFbnRyeUZpbGVUb0NhY2hlKGZpbGVOYW1lOiBzdHJpbmcsIHZhbHVlOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5jb21wb25lbnRzRW50cnlGaWxlc0NhY2hlW2ZpbGVOYW1lXSA9IHZhbHVlO1xyXG4gICAgfVxyXG59XHJcblxyXG5jbGFzcyBJbXBvcnRNb2R1bGVXYWxrZXIgZXh0ZW5kcyBMaW50LlJ1bGVXYWxrZXIge1xyXG4gICAgLyoqXHJcbiAgICAgKiBVcGRhdGUgaW1wb3J0IHBhdGggd2l0aCBtb2R1bGUgZW50cnkgZmlsZS5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBpbXBvcnRFbnRyeUZpbGVGaXhlcihcclxuICAgICAgICBzdGFydDogbnVtYmVyLFxyXG4gICAgICAgIGxlbmd0aDogbnVtYmVyLFxyXG4gICAgICAgIHByZWZpeDogc3RyaW5nLFxyXG4gICAgICAgIG1vZHVsZU5hbWU6IHN0cmluZyxcclxuICAgICAgICBmdWxsTW9kdWxlTmFtZTogc3RyaW5nLFxyXG4gICAgICAgIHF1b3RlU3ltYm9sOiBzdHJpbmdcclxuICAgICk6IExpbnQuUmVwbGFjZW1lbnQge1xyXG5cclxuICAgICAgICBjb25zdCByZXNvbHZlZEltcG9ydCA9IFtcclxuICAgICAgICAgICAgcHJlZml4ICsgUnVsZS5zZWFyY2hNb2R1bGVQYXRoLFxyXG4gICAgICAgICAgICBtb2R1bGVOYW1lLFxyXG4gICAgICAgICAgICBmdWxsTW9kdWxlTmFtZSArIHF1b3RlU3ltYm9sXHJcbiAgICAgICAgXS5qb2luKFJ1bGUuc2VwKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIG5ldyBMaW50LlJlcGxhY2VtZW50KHN0YXJ0LCBsZW5ndGgsIHJlc29sdmVkSW1wb3J0KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENoYW5nZSBwYXRoIHRvIHJlbGF0aXZlLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGltcG9ydFdpdGhSZWxhdGl2ZVBhdGhGaXhlcihcclxuICAgICAgICBzdGFydDogbnVtYmVyLFxyXG4gICAgICAgIGxlbmd0aDogbnVtYmVyLFxyXG4gICAgICAgIGltcG9ydEZpbGVOYW1lOiBzdHJpbmcsXHJcbiAgICAgICAgc291cmNlU3BsaXRQYXRoOiBzdHJpbmdbXSxcclxuICAgICAgICBpbXBvcnRTcGxpdFBhdGg6IHN0cmluZ1tdLFxyXG4gICAgICAgIHF1b3RlU3ltYm9sOiBzdHJpbmdcclxuICAgICk6IExpbnQuUmVwbGFjZW1lbnQge1xyXG5cclxuICAgICAgICBjb25zdCBzb3VyY2VQYXRoID0gc291cmNlU3BsaXRQYXRoLnNsaWNlKDAsIC0xKS5qb2luKFJ1bGUuc2VwKTtcclxuICAgICAgICBjb25zdCBpbXBvcnRQYXRoID0gaW1wb3J0U3BsaXRQYXRoLnNsaWNlKDAsIC0xKS5qb2luKFJ1bGUuc2VwKTtcclxuXHJcbiAgICAgICAgY29uc3QgcmVsYXRpdmVQYXRoID0gcGF0aC5yZWxhdGl2ZShzb3VyY2VQYXRoLCBpbXBvcnRQYXRoKS5zcGxpdChwYXRoLnNlcCk7XHJcbiAgICAgICAgcmVsYXRpdmVQYXRoLnB1c2goaW1wb3J0RmlsZU5hbWUpO1xyXG5cclxuICAgICAgICBsZXQgcmVsYXRpdmVQYXRoU3RyaW5nID0gcmVsYXRpdmVQYXRoLmpvaW4oUnVsZS5zZXApO1xyXG5cclxuICAgICAgICBpZiAocmVsYXRpdmVQYXRoU3RyaW5nWzBdID09PSBSdWxlLnNlcCkge1xyXG4gICAgICAgICAgICByZWxhdGl2ZVBhdGhTdHJpbmcgPSBcIi5cIiArIHJlbGF0aXZlUGF0aFN0cmluZztcclxuICAgICAgICB9IGVsc2UgaWYgKHJlbGF0aXZlUGF0aFN0cmluZ1swXSAhPT0gXCIuXCIpIHtcclxuICAgICAgICAgICAgcmVsYXRpdmVQYXRoU3RyaW5nID0gYC4ke1J1bGUuc2VwfSR7cmVsYXRpdmVQYXRoU3RyaW5nfWA7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBmaXhlZFBhdGggPSBgJHtxdW90ZVN5bWJvbH0ke3JlbGF0aXZlUGF0aFN0cmluZ30ke3F1b3RlU3ltYm9sfWA7XHJcblxyXG4gICAgICAgIHJldHVybiBuZXcgTGludC5SZXBsYWNlbWVudChzdGFydCwgbGVuZ3RoLCBmaXhlZFBhdGgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhdGUgcGF0aCBkZXRhaWxzIG9iamVjdCBmcm9tIHBhdGhuYW1lLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHBhcnNlUGF0aERldGFpbHMocGF0aG5hbWU6IHN0cmluZywgd2l0aFF1b3RlczogYm9vbGVhbiA9IHRydWUpOiBQYXRoRGV0YWlscyB7XHJcbiAgICAgICAgY29uc3QgW3ByZWZpeCwgc3VmZml4XSA9IHBhdGhuYW1lLnNwbGl0KFJ1bGUuc2VhcmNoTW9kdWxlUGF0aFNwbGl0dGVyKTtcclxuICAgICAgICBjb25zdCBbbW9kdWxlTmFtZSwgLi4uaW1wb3J0U3BsaXRQYXRoXSA9IHN1ZmZpeC5zcGxpdChSdWxlLnNlcCk7XHJcblxyXG4gICAgICAgIGlmICh3aXRoUXVvdGVzKSB7XHJcbiAgICAgICAgICAgIGltcG9ydFNwbGl0UGF0aFtpbXBvcnRTcGxpdFBhdGgubGVuZ3RoIC0gMV0gPSBpbXBvcnRTcGxpdFBhdGhbaW1wb3J0U3BsaXRQYXRoLmxlbmd0aCAtIDFdLnNsaWNlKDAsIC0xKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IFtmaWxlTmFtZV0gPSBpbXBvcnRTcGxpdFBhdGguc2xpY2UoLTEpO1xyXG5cclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBwcmVmaXg6IHByZWZpeCxcclxuICAgICAgICAgICAgc3VmZml4OiBzdWZmaXgsXHJcbiAgICAgICAgICAgIG1vZHVsZU5hbWU6IG1vZHVsZU5hbWUsXHJcbiAgICAgICAgICAgIGZ1bGxNb2R1bGVOYW1lOiBSdWxlLnJlc29sdmVNb2R1bGVGaWxlbmFtZShtb2R1bGVOYW1lKSxcclxuICAgICAgICAgICAgc3BsaXRQYXRoOiBpbXBvcnRTcGxpdFBhdGgsXHJcbiAgICAgICAgICAgIGZpbGVOYW1lOiBmaWxlTmFtZSxcclxuICAgICAgICAgICAgd2l0aFF1b3Rlczogd2l0aFF1b3Rlc1xyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBWYWxpZGF0ZSBpbXBvcnQgbGluZS5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBzdGFydFZhbGlkYXRpbmcoc291cmNlRmlsZTogc3RyaW5nLCBpbXBvcnRGaWxlOiBzdHJpbmcsIGltcG9ydFN0YXJ0OiBudW1iZXIsIHF1b3RlOiBzdHJpbmcgPSBcIlwiKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qgc291cmNlRmlsZUlzRnJvbU1vZHVsZSA9IHNvdXJjZUZpbGUuaW5kZXhPZihSdWxlLnNlYXJjaE1vZHVsZVBhdGgpID4gLTE7XHJcbiAgICAgICAgY29uc3QgaW1wb3J0RmlsZUlzRnJvbU1vZHVsZSA9IGltcG9ydEZpbGUuaW5kZXhPZihSdWxlLnNlYXJjaE1vZHVsZVBhdGgpID4gLTE7XHJcblxyXG4gICAgICAgIGlmICghc291cmNlRmlsZUlzRnJvbU1vZHVsZSAmJiAhaW1wb3J0RmlsZUlzRnJvbU1vZHVsZSkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBDaGVjayBpZiBpbXBvcnRpbmcgZmlsZSBpcyBub3QgZnJvbSBtb2R1bGVcclxuICAgICAgICBpZiAoIWltcG9ydEZpbGVJc0Zyb21Nb2R1bGUpIHtcclxuXHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHNvdXJjZSBmaWxlIGlzIGZyb20gbW9kdWxlXHJcbiAgICAgICAgICAgIGlmIChzb3VyY2VGaWxlSXNGcm9tTW9kdWxlKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2VEZXRhaWxzID0gdGhpcy5wYXJzZVBhdGhEZXRhaWxzKHNvdXJjZUZpbGUsIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGltcG9ydEZpbGVOYW1lID0gaW1wb3J0RmlsZS5zcGxpdChSdWxlLnNlcCkuc2xpY2UoLTEpWzBdLnNsaWNlKDAsIC0xKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldEZpbGVOYW1lID0gc291cmNlRGV0YWlscy5mdWxsTW9kdWxlTmFtZTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBtb2R1bGUgaXRzZWxmIGRvZXNuJ3QgaW1wb3J0IGZyb20gZW50cnkgZmlsZVxyXG4gICAgICAgICAgICAgICAgaWYgKGltcG9ydEZpbGVOYW1lID09PSB0YXJnZXRGaWxlTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkRmFpbHVyZUF0KGltcG9ydFN0YXJ0LCBpbXBvcnRGaWxlLmxlbmd0aCwgUnVsZS5pbnNpZGVFbnRyeUZhaWx1cmVTdHJpbmcpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGltcG9ydERldGFpbHMgPSB0aGlzLnBhcnNlUGF0aERldGFpbHMoaW1wb3J0RmlsZSwgQm9vbGVhbihxdW90ZSkpO1xyXG4gICAgICAgIGlmIChzb3VyY2VGaWxlSXNGcm9tTW9kdWxlICYmIGltcG9ydEZpbGVJc0Zyb21Nb2R1bGUpIHtcclxuICAgICAgICAgICAgY29uc3Qgc291cmNlRGV0YWlscyA9IHRoaXMucGFyc2VQYXRoRGV0YWlscyhzb3VyY2VGaWxlLCBmYWxzZSk7XHJcbiAgICAgICAgICAgIGlmIChzb3VyY2VEZXRhaWxzLm1vZHVsZU5hbWUgPT09IGltcG9ydERldGFpbHMubW9kdWxlTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZml4ID0gdGhpcy5pbXBvcnRXaXRoUmVsYXRpdmVQYXRoRml4ZXIoXHJcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0U3RhcnQsXHJcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0RmlsZS5sZW5ndGgsXHJcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0RGV0YWlscy5maWxlTmFtZSxcclxuICAgICAgICAgICAgICAgICAgICBzb3VyY2VEZXRhaWxzLnNwbGl0UGF0aCxcclxuICAgICAgICAgICAgICAgICAgICBpbXBvcnREZXRhaWxzLnNwbGl0UGF0aCxcclxuICAgICAgICAgICAgICAgICAgICBxdW90ZVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuYWRkRmFpbHVyZUF0KGltcG9ydFN0YXJ0LCBpbXBvcnRGaWxlLmxlbmd0aCwgUnVsZS5pbnNpZGVSZWxhdGl2ZUZhaWx1cmVTdHJpbmcsIGZpeCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChpbXBvcnRGaWxlSXNGcm9tTW9kdWxlICYmIChpbXBvcnREZXRhaWxzLnNwbGl0UGF0aC5sZW5ndGggPiAxIHx8IGltcG9ydERldGFpbHMuZnVsbE1vZHVsZU5hbWUgIT09IGltcG9ydERldGFpbHMuZmlsZU5hbWUpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGZyb21DYWNoZSA9IFJ1bGUuZ2V0Q29tcG9uZW50RW50cnlGaWxlRnJvbUNhY2hlKGltcG9ydERldGFpbHMuZnVsbE1vZHVsZU5hbWUpO1xyXG4gICAgICAgICAgICBsZXQgaXNDb21wb25lbnRzV2l0aEVudHJ5OiBib29sZWFuO1xyXG4gICAgICAgICAgICBpZiAoZnJvbUNhY2hlID09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIGlzQ29tcG9uZW50c1dpdGhFbnRyeSA9IGZzLmV4aXN0c1N5bmMoaW1wb3J0RGV0YWlscy5mdWxsTW9kdWxlTmFtZSk7XHJcbiAgICAgICAgICAgICAgICBSdWxlLnNldENvbXBvbmVudEVudHJ5RmlsZVRvQ2FjaGUoaW1wb3J0RGV0YWlscy5mdWxsTW9kdWxlTmFtZSwgaXNDb21wb25lbnRzV2l0aEVudHJ5KTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGlzQ29tcG9uZW50c1dpdGhFbnRyeSA9IGZyb21DYWNoZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKGlzQ29tcG9uZW50c1dpdGhFbnRyeSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZml4ID0gdGhpcy5pbXBvcnRFbnRyeUZpbGVGaXhlcihcclxuICAgICAgICAgICAgICAgICAgICBpbXBvcnRTdGFydCxcclxuICAgICAgICAgICAgICAgICAgICBpbXBvcnRGaWxlLmxlbmd0aCxcclxuICAgICAgICAgICAgICAgICAgICBpbXBvcnREZXRhaWxzLnByZWZpeCxcclxuICAgICAgICAgICAgICAgICAgICBpbXBvcnREZXRhaWxzLm1vZHVsZU5hbWUsXHJcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0RGV0YWlscy5mdWxsTW9kdWxlTmFtZSxcclxuICAgICAgICAgICAgICAgICAgICBxdW90ZVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuYWRkRmFpbHVyZUF0KGltcG9ydFN0YXJ0LCBpbXBvcnRGaWxlLmxlbmd0aCwgUnVsZS5lbnRyeUZhaWx1cmVTdHJpbmcsIGZpeCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN0YXJ0VmFsaWRhdGluZ1JlRXhwb3J0QWxsKGZ1bGxUZXh0OiBzdHJpbmcsIHNvdXJjZUZpbGU6IHN0cmluZywgbm9kZTogdHMuU3RhdGVtZW50KTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qgc291cmNlRmlsZUlzRnJvbU1vZHVsZSA9IHNvdXJjZUZpbGUuaW5kZXhPZihSdWxlLnNlYXJjaE1vZHVsZVBhdGgpID4gLTE7XHJcbiAgICAgICAgaWYgKHNvdXJjZUZpbGVJc0Zyb21Nb2R1bGUgJiYgUnVsZS5yZWV4cG9ydEFsbFBhdGhSZWdleC50ZXN0KGZ1bGxUZXh0KSkge1xyXG4gICAgICAgICAgICB0aGlzLmFkZEZhaWx1cmVBdE5vZGUobm9kZSwgUnVsZS5mb3JiaWRkZW5SZWV4cG9ydEFsbEZhaWx1cmVTdHJpbmcpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFZpc2l0IG9uIGltcG9ydCBkZWNsYXJhdGlvbiBmb3VuZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHZpc2l0SW1wb3J0RGVjbGFyYXRpb24obm9kZTogdHMuSW1wb3J0RGVjbGFyYXRpb24pOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBzb3VyY2VGaWxlID0gbm9kZS5nZXRTb3VyY2VGaWxlKCkuZmlsZU5hbWU7XHJcbiAgICAgICAgY29uc3QgaW1wb3J0RmlsZSA9IG5vZGUubW9kdWxlU3BlY2lmaWVyLmdldFRleHQoKTtcclxuICAgICAgICBjb25zdCBpbXBvcnRTdGFydCA9IG5vZGUubW9kdWxlU3BlY2lmaWVyLmdldFN0YXJ0KCk7XHJcbiAgICAgICAgY29uc3QgcXVvdGVTeW1ib2wgPSBpbXBvcnRGaWxlWzBdO1xyXG5cclxuICAgICAgICB0aGlzLnN0YXJ0VmFsaWRhdGluZyhzb3VyY2VGaWxlLCBpbXBvcnRGaWxlLCBpbXBvcnRTdGFydCwgcXVvdGVTeW1ib2wpO1xyXG5cclxuICAgICAgICBzdXBlci52aXNpdEltcG9ydERlY2xhcmF0aW9uKG5vZGUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVmlzaXQgb24gYW55IHNvdXJjZSBmaWxlLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdmlzaXRTb3VyY2VGaWxlKG5vZGU6IHRzLlNvdXJjZUZpbGUpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBmdWxsVGV4dCA9IG5vZGUuZ2V0RnVsbFRleHQoKTtcclxuICAgICAgICBjb25zdCBzb3VyY2VGaWxlID0gbm9kZS5maWxlTmFtZTtcclxuXHJcbiAgICAgICAgaWYgKG5vZGUuc3RhdGVtZW50cy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIG5vZGUuc3RhdGVtZW50c1xyXG4gICAgICAgICAgICAgICAgLmZpbHRlcih4ID0+IHgua2luZCA9PT0gdHMuU3ludGF4S2luZC5FeHBvcnREZWNsYXJhdGlvbiAmJiB4LmdldEZ1bGxUZXh0KCkuaW5kZXhPZihcImZyb21cIikgPiAtMSlcclxuICAgICAgICAgICAgICAgIC5mb3JFYWNoKHN0YXRlbWVudCA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGV4dCA9IHN0YXRlbWVudC5nZXRGdWxsVGV4dCgpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWdleFJlc3VsdCA9IFJ1bGUucmVleHBvcnRQYXRoUmVnZXguZXhlYyh0ZXh0KTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAocmVnZXhSZXN1bHQgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBpbXBvcnRGaWxlID0gcmVnZXhSZXN1bHRbMV07XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGltcG9ydEZpbGUgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0VmFsaWRhdGluZ1JlRXhwb3J0QWxsKHRleHQsIHNvdXJjZUZpbGUsIHN0YXRlbWVudCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGltcG9ydFN0YXJ0ID0gZnVsbFRleHQuaW5kZXhPZihpbXBvcnRGaWxlKTtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0VmFsaWRhdGluZyhzb3VyY2VGaWxlLCBpbXBvcnRGaWxlLCBpbXBvcnRTdGFydCk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHN1cGVyLnZpc2l0U291cmNlRmlsZShub2RlKTtcclxuICAgIH1cclxufVxyXG4iXX0=