UNPKG

16.9 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const tslib_1 = require("tslib");
4const ts_utils_1 = require("@neo-one/ts-utils");
5const utils_1 = require("@neo-one/utils");
6const typescript_1 = tslib_1.__importDefault(require("typescript"));
7const createContext_1 = require("./createContext");
8const errors_1 = require("./errors");
9exports.scanContext = (context) => {
10 const smartContract = ts_utils_1.tsUtils.symbol.getDeclarations(context.builtins.getInterfaceSymbol('SmartContract'))[0];
11 if (!typescript_1.default.isInterfaceDeclaration(smartContract)) {
12 throw new Error('Something went wrong!');
13 }
14 const { contracts, dependencies } = ts_utils_1.tsUtils.class_.getImplementors(context.program, context.languageService, smartContract).reduce((acc, derived) => {
15 if (!ts_utils_1.tsUtils.modifier.isAbstract(derived)) {
16 const filePath = ts_utils_1.tsUtils.file.getFilePath(ts_utils_1.tsUtils.node.getSourceFile(derived));
17 const name = ts_utils_1.tsUtils.node.getNameOrThrow(derived);
18 const existing = acc.contracts[filePath];
19 if (existing !== undefined) {
20 throw new errors_1.MultipleContractsInFileError(filePath);
21 }
22 const references = [...new Set(ts_utils_1.tsUtils.reference.findReferencesAsNodes(context.program, context.languageService, derived).map(reference => ts_utils_1.tsUtils.file.getFilePath(ts_utils_1.tsUtils.node.getSourceFile(reference))))];
23 const dependency = {
24 filePath,
25 name
26 };
27 const dependenciesOut = references.reduce((innerAcc, reference) => {
28 let filePathDependencies = innerAcc[reference];
29 if (filePathDependencies === undefined) {
30 filePathDependencies = [];
31 }
32 return Object.assign({}, innerAcc, { [reference]: [...filePathDependencies, dependency] });
33 }, acc.dependencies);
34 return {
35 contracts: Object.assign({}, acc.contracts, { [filePath]: {
36 filePath,
37 name,
38 dependencies: []
39 } }),
40 dependencies: dependenciesOut
41 };
42 }
43 return acc;
44 }, {
45 contracts: {},
46 dependencies: {}
47 });
48 const unsortedContracts = Object.values(contracts).map(contract => {
49 const filePathDependencies = dependencies[contract.filePath];
50 return Object.assign({}, contract, { dependencies: filePathDependencies === undefined ? [] : filePathDependencies });
51 });
52 return topographicalSort(unsortedContracts);
53};
54const topographicalSort = (contracts) => {
55 const contractToDependencies = contracts.reduce((acc, contract) => (Object.assign({}, acc, { [contract.filePath]: new Set(contract.dependencies.map(dep => dep.filePath)) })), {});
56 const mutableOut = [];
57 const satisfied = contracts.filter(contract => contract.dependencies.length === 0);
58 let remaining = contracts.filter(contract => contract.dependencies.length !== 0); // tslint:disable-next-line no-loop-statement
59 while (satisfied.length > 0) {
60 // tslint:disable-next-line no-array-mutation
61 const node = satisfied.shift();
62 if (node === undefined) {
63 /* istanbul ignore next */
64 break;
65 }
66 mutableOut.push(node);
67 remaining = remaining.map(contract => {
68 const deps = contractToDependencies[contract.filePath];
69 deps.delete(node.filePath);
70 if (deps.size === 0) {
71 // tslint:disable-next-line no-array-mutation
72 satisfied.push(contract);
73 return undefined;
74 }
75 return contract;
76 }).filter(utils_1.utils.notNull);
77 }
78 if (mutableOut.length !== contracts.length) {
79 throw new errors_1.CircularLinkedDependencyError();
80 }
81 return mutableOut;
82};
83exports.scan = async (dir) => {
84 const context = await createContext_1.createContextForDir(dir);
85 return exports.scanContext(context);
86};
87
88//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNjYW4udHMiXSwibmFtZXMiOlsic2NhbkNvbnRleHQiLCJjb250ZXh0Iiwic21hcnRDb250cmFjdCIsInRzVXRpbHMiLCJzeW1ib2wiLCJnZXREZWNsYXJhdGlvbnMiLCJidWlsdGlucyIsImdldEludGVyZmFjZVN5bWJvbCIsInRzIiwiaXNJbnRlcmZhY2VEZWNsYXJhdGlvbiIsIkVycm9yIiwiY29udHJhY3RzIiwiZGVwZW5kZW5jaWVzIiwiY2xhc3NfIiwiZ2V0SW1wbGVtZW50b3JzIiwicHJvZ3JhbSIsImxhbmd1YWdlU2VydmljZSIsInJlZHVjZSIsImFjYyIsImRlcml2ZWQiLCJtb2RpZmllciIsImlzQWJzdHJhY3QiLCJmaWxlUGF0aCIsImZpbGUiLCJnZXRGaWxlUGF0aCIsIm5vZGUiLCJnZXRTb3VyY2VGaWxlIiwibmFtZSIsImdldE5hbWVPclRocm93IiwiZXhpc3RpbmciLCJ1bmRlZmluZWQiLCJNdWx0aXBsZUNvbnRyYWN0c0luRmlsZUVycm9yIiwicmVmZXJlbmNlcyIsIlNldCIsInJlZmVyZW5jZSIsImZpbmRSZWZlcmVuY2VzQXNOb2RlcyIsIm1hcCIsImRlcGVuZGVuY3kiLCJkZXBlbmRlbmNpZXNPdXQiLCJpbm5lckFjYyIsImZpbGVQYXRoRGVwZW5kZW5jaWVzIiwidW5zb3J0ZWRDb250cmFjdHMiLCJPYmplY3QiLCJ2YWx1ZXMiLCJjb250cmFjdCIsInRvcG9ncmFwaGljYWxTb3J0IiwiY29udHJhY3RUb0RlcGVuZGVuY2llcyIsImRlcCIsIm11dGFibGVPdXQiLCJzYXRpc2ZpZWQiLCJmaWx0ZXIiLCJsZW5ndGgiLCJyZW1haW5pbmciLCJzaGlmdCIsInB1c2giLCJkZXBzIiwiZGVsZXRlIiwic2l6ZSIsInV0aWxzIiwibm90TnVsbCIsIkNpcmN1bGFyTGlua2VkRGVwZW5kZW5jeUVycm9yIiwic2NhbiIsImRpciIsImNyZWF0ZUNvbnRleHRGb3JEaXIiXSwibWFwcGluZ3MiOiI7OztBQUFBLGdEQUFBO0FBQ0EsMENBQUE7QUFDQSxvRUFBQTtBQUVBLG1EQUFBO0FBQ0EscUNBQUE7QUFvQmFBLFFBQUFBLFdBQVcsR0FBRyxDQUFDQyxPQUFELEVBQUEsRUFBQTtJQUN6QixNQUFNQyxhQUFhLEdBQUdDLGtCQUFPLENBQUNDLE1BQVIsQ0FBZUMsZUFBZixDQUErQkosT0FBTyxDQUFDSyxRQUFSLENBQWlCQyxrQkFBakIsQ0FBb0MsZUFBcEMsQ0FBL0IsQ0FBQSxDQUFxRixDQUFyRixDQUF0QixDQUFBO0lBQ0EsSUFBSSxDQUFDQyxvQkFBRSxDQUFDQyxzQkFBSCxDQUEwQlAsYUFBMUIsQ0FBTCxFQUErQztRQUM3QyxNQUFNLElBQUlRLEtBQUosQ0FBVSx1QkFBVixDQUFOLENBQUE7S0FDRDtJQUVELE1BQU0sRUFBRUMsU0FBRixFQUFhQyxZQUFBQSxFQUFiLEdBQThCVCxrQkFBTyxDQUFDVSxNQUFSLENBQ2pDQyxlQURpQyxDQUNqQmIsT0FBTyxDQUFDYyxPQURTLEVBQ0FkLE9BQU8sQ0FBQ2UsZUFEUixFQUN5QmQsYUFEekIsQ0FBQSxDQUVqQ2UsTUFBTSxDQUNMLENBQUNDLEdBQUQsRUFBTUMsT0FBTixFQUFBLEVBQUE7UUFDRSxJQUFJLENBQUNoQixrQkFBTyxDQUFDaUIsUUFBUixDQUFpQkMsVUFBakIsQ0FBNEJGLE9BQTVCLENBQUwsRUFBMkM7WUFDekMsTUFBTUcsUUFBUSxHQUFHbkIsa0JBQU8sQ0FBQ29CLElBQVIsQ0FBYUMsV0FBYixDQUF5QnJCLGtCQUFPLENBQUNzQixJQUFSLENBQWFDLGFBQWIsQ0FBMkJQLE9BQTNCLENBQXpCLENBQWpCLENBQUE7WUFDQSxNQUFNUSxJQUFJLEdBQUd4QixrQkFBTyxDQUFDc0IsSUFBUixDQUFhRyxjQUFiLENBQTRCVCxPQUE1QixDQUFiLENBQUE7WUFDQSxNQUFNVSxRQUFRLEdBQUdYLEdBQUcsQ0FBQ1AsU0FBSixDQUFjVyxRQUFkLENBQWpCLENBQUE7WUFDQSxJQUFJTyxRQUFRLEtBQUtDLFNBQWpCLEVBQTRCO2dCQUMxQixNQUFNLElBQUlDLHFDQUFKLENBQWlDVCxRQUFqQyxDQUFOLENBQUE7YUFDRDtZQUVELE1BQU1VLFVBQVUsR0FBRyxDQUNqQixHQUFHLElBQUlDLEdBQUosQ0FDRDlCLGtCQUFPLENBQUMrQixTQUFSLENBQ0dDLHFCQURILENBQ3lCbEMsT0FBTyxDQUFDYyxPQURqQyxFQUMwQ2QsT0FBTyxDQUFDZSxlQURsRCxFQUNtRUcsT0FEbkUsQ0FBQSxDQUVHaUIsR0FGSCxDQUVRRixTQUFELENBQUEsRUFBQSxDQUFlL0Isa0JBQU8sQ0FBQ29CLElBQVIsQ0FBYUMsV0FBYixDQUF5QnJCLGtCQUFPLENBQUNzQixJQUFSLENBQWFDLGFBQWIsQ0FBMkJRLFNBQTNCLENBQXpCLENBRnRCLENBREMsQ0FEYyxDQUFuQixDQUFBO1lBUUEsTUFBTUcsVUFBVSxHQUFHO2dCQUFFZixRQUFGO2dCQUFZSyxJQUFBQTthQUEvQixDQUFBO1lBQ0EsTUFBTVcsZUFBZSxHQUFHTixVQUFVLENBQUNmLE1BQVgsQ0FBa0IsQ0FBQ3NCLFFBQUQsRUFBV0wsU0FBWCxFQUFBLEVBQUE7Z0JBQ3hDLElBQUlNLG9CQUFvQixHQUFHRCxRQUFRLENBQUNMLFNBQUQsQ0FBbkMsQ0FBQTtnQkFDQSxJQUFJTSxvQkFBb0IsS0FBS1YsU0FBN0IsRUFBd0M7b0JBQ3RDVSxvQkFBb0IsR0FBRyxFQUF2QixDQUFBO2lCQUNEO2dCQUVELHlCQUNLRCxRQURFLElBRUwsQ0FBQ0wsU0FBRCxDQUFBLEVBQWEsQ0FBQyxHQUFHTSxvQkFBSixFQUEwQkgsVUFBMUIsQ0FBQSxJQUZmO1lBSUQsQ0FWdUIsRUFVckJuQixHQUFHLENBQUNOLFlBVmlCLENBQXhCLENBQUE7WUFZQSxPQUFPO2dCQUNMRCxTQUFTLG9CQUNKTyxHQUFHLENBQUNQLFNBREUsSUFFVCxDQUFDVyxRQUFELENBQUEsRUFBWTt3QkFDVkEsUUFEVTt3QkFFVkssSUFGVTt3QkFHVmYsWUFBWSxFQUFFLEVBQUE7cUJBSEosR0FIVDtnQkFTTEEsWUFBWSxFQUFFMEIsZUFBQUE7YUFUaEIsQ0FBQTtTQVdEO1FBRUQsT0FBT3BCLEdBQVAsQ0FBQTtJQUNELENBL0MrQixFQWdEaEM7UUFBRVAsU0FBUyxFQUFFLEVBQWI7UUFBaUJDLFlBQVksRUFBRSxFQUFBO0tBaERDLENBQXBDLENBQUE7SUFtREEsTUFBTTZCLGlCQUFpQixHQUFHQyxNQUFNLENBQUNDLE1BQVAsQ0FBY2hDLFNBQWQsQ0FBQSxDQUF5QnlCLEdBQXpCLENBQThCUSxRQUFELENBQUEsRUFBQTtRQUNyRCxNQUFNSixvQkFBb0IsR0FBRzVCLFlBQVksQ0FBQ2dDLFFBQVEsQ0FBQ3RCLFFBQVYsQ0FBekMsQ0FBQTtRQUVBLHlCQUNLc0IsUUFERSxJQUVMaEMsWUFBWSxFQUFFNEIsb0JBQW9CLEtBQUtWLFNBQXpCLENBQUEsQ0FBQSxDQUFxQyxFQUFyQyxDQUFBLENBQUEsQ0FBMENVLG9CQUFBQSxJQUYxRDtJQUlELENBUHlCLENBQTFCLENBQUE7SUFTQSxPQUFPSyxpQkFBaUIsQ0FBQ0osaUJBQUQsQ0FBeEIsQ0FBQTtBQUNELENBbkVNLENBQUE7QUFxRVAsTUFBTUksaUJBQWlCLEdBQUcsQ0FBQ2xDLFNBQUQsRUFBQSxFQUFBO0lBQ3hCLE1BQU1tQyxzQkFBc0IsR0FBR25DLFNBQVMsQ0FBQ00sTUFBTSxDQUM3QyxDQUFDQyxHQUFELEVBQU0wQixRQUFOLEVBQUEsRUFBQSxDQUFBLG1CQUNLMUIsR0FEZSxJQUVsQixDQUFDMEIsUUFBUSxDQUFDdEIsUUFBVixDQUFBLEVBQXFCLElBQUlXLEdBQUosQ0FBUVcsUUFBUSxDQUFDaEMsWUFBVCxDQUFzQndCLEdBQXRCLENBQTJCVyxHQUFELENBQUEsRUFBQSxDQUFTQSxHQUFHLENBQUN6QixRQUF2QyxDQUFSLENBQUEsSUFITSxFQUs3QixFQUw2QixDQUEvQixDQUFBO0lBT0EsTUFBTTBCLFVBQVUsR0FBZSxFQUEvQixDQUFBO0lBQ0EsTUFBTUMsU0FBUyxHQUFHdEMsU0FBUyxDQUFDdUMsTUFBVixDQUFrQk4sUUFBRCxDQUFBLEVBQUEsQ0FBY0EsUUFBUSxDQUFDaEMsWUFBVCxDQUFzQnVDLE1BQXRCLEtBQWlDLENBQWhFLENBQWxCLENBQUE7SUFDQSxJQUFJQyxTQUFTLEdBQUd6QyxTQUFTLENBQUN1QyxNQUFWLENBQWtCTixRQUFELENBQUEsRUFBQSxDQUFjQSxRQUFRLENBQUNoQyxZQUFULENBQXNCdUMsTUFBdEIsS0FBaUMsQ0FBaEUsQ0FBaEIsQ0FWNkQsQ0FXN0QsNkNBQUE7SUFDQSxPQUFPRixTQUFTLENBQUNFLE1BQVYsR0FBbUIsQ0FBMUIsRUFBNkI7UUFDM0IsNkNBQUE7UUFDQSxNQUFNMUIsSUFBSSxHQUFHd0IsU0FBUyxDQUFDSSxLQUFWLEVBQWIsQ0FBQTtRQUNBLElBQUk1QixJQUFJLEtBQUtLLFNBQWIsRUFBd0I7WUFDdEIsMEJBQUE7WUFDQSxNQUFBO1NBQ0Q7UUFFRGtCLFVBQVUsQ0FBQ00sSUFBWCxDQUFnQjdCLElBQWhCLENBQUEsQ0FBQTtRQUNBMkIsU0FBUyxHQUFHQSxTQUFTLENBQ2xCaEIsR0FEUyxDQUNKUSxRQUFELENBQUEsRUFBQTtZQUNILE1BQU1XLElBQUksR0FBR1Qsc0JBQXNCLENBQUNGLFFBQVEsQ0FBQ3RCLFFBQVYsQ0FBbkMsQ0FBQTtZQUNBaUMsSUFBSSxDQUFDQyxNQUFMLENBQVkvQixJQUFJLENBQUNILFFBQWpCLENBQUEsQ0FBQTtZQUNBLElBQUlpQyxJQUFJLENBQUNFLElBQUwsS0FBYyxDQUFsQixFQUFxQjtnQkFDbkIsNkNBQUE7Z0JBQ0FSLFNBQVMsQ0FBQ0ssSUFBVixDQUFlVixRQUFmLENBQUEsQ0FBQTtnQkFFQSxPQUFPZCxTQUFQLENBQUE7YUFDRDtZQUVELE9BQU9jLFFBQVAsQ0FBQTtRQUNELENBWlMsQ0FBQSxDQWFUTSxNQWJTLENBYUZRLGFBQUssQ0FBQ0MsT0FiSixDQUFaLENBQUE7S0FjRDtJQUVELElBQUlYLFVBQVUsQ0FBQ0csTUFBWCxLQUFzQnhDLFNBQVMsQ0FBQ3dDLE1BQXBDLEVBQTRDO1FBQzFDLE1BQU0sSUFBSVMsc0NBQUosRUFBTixDQUFBO0tBQ0Q7SUFFRCxPQUFPWixVQUFQLENBQUE7QUFDRCxDQTFDRCxDQUFBO0FBNENhYSxRQUFBQSxJQUFJLEdBQUcsS0FBQSxFQUFPQyxHQUFQLEVBQUEsRUFBQTtJQUNsQixNQUFNN0QsT0FBTyxHQUFHLE1BQU04RCxtQ0FBbUIsQ0FBQ0QsR0FBRCxDQUF6QyxDQUFBO0lBRUEsT0FBTzlELG1CQUFXLENBQUNDLE9BQUQsQ0FBbEIsQ0FBQTtBQUNELENBSk0sQ0FBQSIsImZpbGUiOiJuZW8tb25lLXNtYXJ0LWNvbnRyYWN0LWNvbXBpbGVyL3NyYy9zY2FuLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgdHNVdGlscyB9IGZyb20gJ0BuZW8tb25lL3RzLXV0aWxzJztcbmltcG9ydCB7IHV0aWxzIH0gZnJvbSAnQG5lby1vbmUvdXRpbHMnO1xuaW1wb3J0IHRzIGZyb20gJ3R5cGVzY3JpcHQnO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gJy4vQ29udGV4dCc7XG5pbXBvcnQgeyBjcmVhdGVDb250ZXh0Rm9yRGlyIH0gZnJvbSAnLi9jcmVhdGVDb250ZXh0JztcbmltcG9ydCB7IENpcmN1bGFyTGlua2VkRGVwZW5kZW5jeUVycm9yLCBNdWx0aXBsZUNvbnRyYWN0c0luRmlsZUVycm9yIH0gZnJvbSAnLi9lcnJvcnMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbnRyYWN0RGVwZW5kZW5jeSB7XG4gIHJlYWRvbmx5IGZpbGVQYXRoOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbn1cbmV4cG9ydCBpbnRlcmZhY2UgQ29udHJhY3Qge1xuICByZWFkb25seSBmaWxlUGF0aDogc3RyaW5nO1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGRlcGVuZGVuY2llczogUmVhZG9ubHlBcnJheTxDb250cmFjdERlcGVuZGVuY3k+O1xufVxuZXhwb3J0IHR5cGUgQ29udHJhY3RzID0gUmVhZG9ubHlBcnJheTxDb250cmFjdD47XG5cbmludGVyZmFjZSBGaWxlUGF0aFRvQ29udHJhY3Qge1xuICByZWFkb25seSBbZmlsZVBhdGg6IHN0cmluZ106IENvbnRyYWN0O1xufVxuaW50ZXJmYWNlIEZpbGVQYXRoVG9EZXBlbmRlbmNpZXMge1xuICByZWFkb25seSBbZmlsZVBhdGg6IHN0cmluZ106IFJlYWRvbmx5QXJyYXk8Q29udHJhY3REZXBlbmRlbmN5Pjtcbn1cblxuZXhwb3J0IGNvbnN0IHNjYW5Db250ZXh0ID0gKGNvbnRleHQ6IENvbnRleHQpOiBDb250cmFjdHMgPT4ge1xuICBjb25zdCBzbWFydENvbnRyYWN0ID0gdHNVdGlscy5zeW1ib2wuZ2V0RGVjbGFyYXRpb25zKGNvbnRleHQuYnVpbHRpbnMuZ2V0SW50ZXJmYWNlU3ltYm9sKCdTbWFydENvbnRyYWN0JykpWzBdO1xuICBpZiAoIXRzLmlzSW50ZXJmYWNlRGVjbGFyYXRpb24oc21hcnRDb250cmFjdCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1NvbWV0aGluZyB3ZW50IHdyb25nIScpO1xuICB9XG5cbiAgY29uc3QgeyBjb250cmFjdHMsIGRlcGVuZGVuY2llcyB9ID0gdHNVdGlscy5jbGFzc19cbiAgICAuZ2V0SW1wbGVtZW50b3JzKGNvbnRleHQucHJvZ3JhbSwgY29udGV4dC5sYW5ndWFnZVNlcnZpY2UsIHNtYXJ0Q29udHJhY3QpXG4gICAgLnJlZHVjZTx7IGNvbnRyYWN0czogRmlsZVBhdGhUb0NvbnRyYWN0OyBkZXBlbmRlbmNpZXM6IEZpbGVQYXRoVG9EZXBlbmRlbmNpZXMgfT4oXG4gICAgICAoYWNjLCBkZXJpdmVkKSA9PiB7XG4gICAgICAgIGlmICghdHNVdGlscy5tb2RpZmllci5pc0Fic3RyYWN0KGRlcml2ZWQpKSB7XG4gICAgICAgICAgY29uc3QgZmlsZVBhdGggPSB0c1V0aWxzLmZpbGUuZ2V0RmlsZVBhdGgodHNVdGlscy5ub2RlLmdldFNvdXJjZUZpbGUoZGVyaXZlZCkpO1xuICAgICAgICAgIGNvbnN0IG5hbWUgPSB0c1V0aWxzLm5vZGUuZ2V0TmFtZU9yVGhyb3coZGVyaXZlZCk7XG4gICAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBhY2MuY29udHJhY3RzW2ZpbGVQYXRoXSBhcyBDb250cmFjdCB8IHVuZGVmaW5lZDtcbiAgICAgICAgICBpZiAoZXhpc3RpbmcgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IE11bHRpcGxlQ29udHJhY3RzSW5GaWxlRXJyb3IoZmlsZVBhdGgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHJlZmVyZW5jZXMgPSBbXG4gICAgICAgICAgICAuLi5uZXcgU2V0KFxuICAgICAgICAgICAgICB0c1V0aWxzLnJlZmVyZW5jZVxuICAgICAgICAgICAgICAgIC5maW5kUmVmZXJlbmNlc0FzTm9kZXMoY29udGV4dC5wcm9ncmFtLCBjb250ZXh0Lmxhbmd1YWdlU2VydmljZSwgZGVyaXZlZClcbiAgICAgICAgICAgICAgICAubWFwKChyZWZlcmVuY2UpID0+IHRzVXRpbHMuZmlsZS5nZXRGaWxlUGF0aCh0c1V0aWxzLm5vZGUuZ2V0U291cmNlRmlsZShyZWZlcmVuY2UpKSksXG4gICAgICAgICAgICApLFxuICAgICAgICAgIF07XG5cbiAgICAgICAgICBjb25zdCBkZXBlbmRlbmN5ID0geyBmaWxlUGF0aCwgbmFtZSB9O1xuICAgICAgICAgIGNvbnN0IGRlcGVuZGVuY2llc091dCA9IHJlZmVyZW5jZXMucmVkdWNlKChpbm5lckFjYywgcmVmZXJlbmNlKSA9PiB7XG4gICAgICAgICAgICBsZXQgZmlsZVBhdGhEZXBlbmRlbmNpZXMgPSBpbm5lckFjY1tyZWZlcmVuY2VdIGFzIFJlYWRvbmx5QXJyYXk8Q29udHJhY3REZXBlbmRlbmN5PiB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmIChmaWxlUGF0aERlcGVuZGVuY2llcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIGZpbGVQYXRoRGVwZW5kZW5jaWVzID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIC4uLmlubmVyQWNjLFxuICAgICAgICAgICAgICBbcmVmZXJlbmNlXTogWy4uLmZpbGVQYXRoRGVwZW5kZW5jaWVzLCBkZXBlbmRlbmN5XSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSwgYWNjLmRlcGVuZGVuY2llcyk7XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29udHJhY3RzOiB7XG4gICAgICAgICAgICAgIC4uLmFjYy5jb250cmFjdHMsXG4gICAgICAgICAgICAgIFtmaWxlUGF0aF06IHtcbiAgICAgICAgICAgICAgICBmaWxlUGF0aCxcbiAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgICAgIGRlcGVuZGVuY2llczogW10sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVwZW5kZW5jaWVzOiBkZXBlbmRlbmNpZXNPdXQsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhY2M7XG4gICAgICB9LFxuICAgICAgeyBjb250cmFjdHM6IHt9LCBkZXBlbmRlbmNpZXM6IHt9IH0sXG4gICAgKTtcblxuICBjb25zdCB1bnNvcnRlZENvbnRyYWN0cyA9IE9iamVjdC52YWx1ZXMoY29udHJhY3RzKS5tYXAoKGNvbnRyYWN0KSA9PiB7XG4gICAgY29uc3QgZmlsZVBhdGhEZXBlbmRlbmNpZXMgPSBkZXBlbmRlbmNpZXNbY29udHJhY3QuZmlsZVBhdGhdIGFzIFJlYWRvbmx5QXJyYXk8Q29udHJhY3REZXBlbmRlbmN5PiB8IHVuZGVmaW5lZDtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi5jb250cmFjdCxcbiAgICAgIGRlcGVuZGVuY2llczogZmlsZVBhdGhEZXBlbmRlbmNpZXMgPT09IHVuZGVmaW5lZCA/IFtdIDogZmlsZVBhdGhEZXBlbmRlbmNpZXMsXG4gICAgfTtcbiAgfSk7XG5cbiAgcmV0dXJuIHRvcG9ncmFwaGljYWxTb3J0KHVuc29ydGVkQ29udHJhY3RzKTtcbn07XG5cbmNvbnN0IHRvcG9ncmFwaGljYWxTb3J0ID0gKGNvbnRyYWN0czogQ29udHJhY3RzKTogQ29udHJhY3RzID0+IHtcbiAgY29uc3QgY29udHJhY3RUb0RlcGVuZGVuY2llcyA9IGNvbnRyYWN0cy5yZWR1Y2U8eyBbZmlsZVBhdGg6IHN0cmluZ106IFNldDxzdHJpbmc+IH0+KFxuICAgIChhY2MsIGNvbnRyYWN0KSA9PiAoe1xuICAgICAgLi4uYWNjLFxuICAgICAgW2NvbnRyYWN0LmZpbGVQYXRoXTogbmV3IFNldChjb250cmFjdC5kZXBlbmRlbmNpZXMubWFwKChkZXApID0+IGRlcC5maWxlUGF0aCkpLFxuICAgIH0pLFxuICAgIHt9LFxuICApO1xuICBjb25zdCBtdXRhYmxlT3V0OiBDb250cmFjdFtdID0gW107XG4gIGNvbnN0IHNhdGlzZmllZCA9IGNvbnRyYWN0cy5maWx0ZXIoKGNvbnRyYWN0KSA9PiBjb250cmFjdC5kZXBlbmRlbmNpZXMubGVuZ3RoID09PSAwKTtcbiAgbGV0IHJlbWFpbmluZyA9IGNvbnRyYWN0cy5maWx0ZXIoKGNvbnRyYWN0KSA9PiBjb250cmFjdC5kZXBlbmRlbmNpZXMubGVuZ3RoICE9PSAwKTtcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWxvb3Atc3RhdGVtZW50XG4gIHdoaWxlIChzYXRpc2ZpZWQubGVuZ3RoID4gMCkge1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1hcnJheS1tdXRhdGlvblxuICAgIGNvbnN0IG5vZGUgPSBzYXRpc2ZpZWQuc2hpZnQoKTtcbiAgICBpZiAobm9kZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgbXV0YWJsZU91dC5wdXNoKG5vZGUpO1xuICAgIHJlbWFpbmluZyA9IHJlbWFpbmluZ1xuICAgICAgLm1hcCgoY29udHJhY3QpID0+IHtcbiAgICAgICAgY29uc3QgZGVwcyA9IGNvbnRyYWN0VG9EZXBlbmRlbmNpZXNbY29udHJhY3QuZmlsZVBhdGhdO1xuICAgICAgICBkZXBzLmRlbGV0ZShub2RlLmZpbGVQYXRoKTtcbiAgICAgICAgaWYgKGRlcHMuc2l6ZSA9PT0gMCkge1xuICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1hcnJheS1tdXRhdGlvblxuICAgICAgICAgIHNhdGlzZmllZC5wdXNoKGNvbnRyYWN0KTtcblxuICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29udHJhY3Q7XG4gICAgICB9KVxuICAgICAgLmZpbHRlcih1dGlscy5ub3ROdWxsKTtcbiAgfVxuXG4gIGlmIChtdXRhYmxlT3V0Lmxlbmd0aCAhPT0gY29udHJhY3RzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBDaXJjdWxhckxpbmtlZERlcGVuZGVuY3lFcnJvcigpO1xuICB9XG5cbiAgcmV0dXJuIG11dGFibGVPdXQ7XG59O1xuXG5leHBvcnQgY29uc3Qgc2NhbiA9IGFzeW5jIChkaXI6IHN0cmluZyk6IFByb21pc2U8Q29udHJhY3RzPiA9PiB7XG4gIGNvbnN0IGNvbnRleHQgPSBhd2FpdCBjcmVhdGVDb250ZXh0Rm9yRGlyKGRpcik7XG5cbiAgcmV0dXJuIHNjYW5Db250ZXh0KGNvbnRleHQpO1xufTtcbiJdfQ==