UNPKG

d2-ui

Version:
538 lines (420 loc) 43.1 kB
'use strict'; exports.__esModule = true; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); exports.recursivePatternCapture = recursivePatternCapture; require('es6-symbol/implement'); var _es6Map = require('es6-map'); var _es6Map2 = _interopRequireDefault(_es6Map); var _fs = require('fs'); var fs = _interopRequireWildcard(_fs); var _crypto = require('crypto'); var _doctrine = require('doctrine'); var doctrine = _interopRequireWildcard(_doctrine); var _parse2 = require('./parse'); var _parse3 = _interopRequireDefault(_parse2); var _resolve = require('./resolve'); var _resolve2 = _interopRequireDefault(_resolve); var _ignore = require('./ignore'); var _ignore2 = _interopRequireDefault(_ignore); var _hash = require('./hash'); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var exportCache = new _es6Map2.default(); /** * detect exports without a full parse. * used primarily to ignore the import/ignore setting, iif it looks like * there might be something there (i.e., jsnext:main is set). * @type {RegExp} */ var hasExports = new RegExp('(^|[\\n;])\\s*export\\s[\\w{*]'); var ExportMap = function () { function ExportMap(path) { _classCallCheck(this, ExportMap); this.path = path; this.namespace = new _es6Map2.default(); // todo: restructure to key on path, value is resolver + map of names this.reexports = new _es6Map2.default(); this.dependencies = new _es6Map2.default(); this.errors = []; } ExportMap.get = function get(source, context) { var path = (0, _resolve2.default)(source, context); if (path == null) return null; return ExportMap.for(path, context); }; ExportMap.for = function _for(path, context) { var exportMap = void 0; var cacheKey = (0, _hash.hashObject)((0, _crypto.createHash)('sha256'), { settings: context.settings, parserPath: context.parserPath, parserOptions: context.parserOptions, path: path }).digest('hex'); exportMap = exportCache.get(cacheKey); // return cached ignore if (exportMap === null) return null; var stats = fs.statSync(path); if (exportMap != null) { // date equality check if (exportMap.mtime - stats.mtime === 0) { return exportMap; } // future: check content equality? } var content = fs.readFileSync(path, { encoding: 'utf8' }); // check for and cache ignore if ((0, _ignore2.default)(path, context) && !hasExports.test(content)) { exportCache.set(cacheKey, null); return null; } exportMap = ExportMap.parse(path, content, context); exportMap.mtime = stats.mtime; exportCache.set(cacheKey, exportMap); return exportMap; }; ExportMap.parse = function parse(path, content, context) { var m = new ExportMap(path); try { var ast = (0, _parse3.default)(content, context); } catch (err) { m.errors.push(err); return m; // can't continue } // attempt to collect module doc ast.comments.some(function (c) { if (c.type !== 'Block') return false; try { var doc = doctrine.parse(c.value, { unwrap: true }); if (doc.tags.some(function (t) { return t.title === 'module'; })) { m.doc = doc; return true; } } catch (err) {/* ignore */} return false; }); var namespaces = new _es6Map2.default(); function remotePath(node) { return _resolve2.default.relative(node.source.value, path, context.settings); } function resolveImport(node) { var rp = remotePath(node); if (rp == null) return null; return ExportMap.for(rp, context); } function getNamespace(identifier) { if (!namespaces.has(identifier.name)) return; return function () { return resolveImport(namespaces.get(identifier.name)); }; } function addNamespace(object, identifier) { var nsfn = getNamespace(identifier); if (nsfn) { Object.defineProperty(object, 'namespace', { get: nsfn }); } return object; } ast.body.forEach(function (n) { if (n.type === 'ExportDefaultDeclaration') { var exportMeta = captureDoc(n); if (n.declaration.type === 'Identifier') { addNamespace(exportMeta, n.declaration); } m.namespace.set('default', exportMeta); return; } if (n.type === 'ExportAllDeclaration') { var _ret = function () { var remoteMap = remotePath(n); if (remoteMap == null) return { v: void 0 }; m.dependencies.set(remoteMap, function () { return ExportMap.for(remoteMap, context); }); return { v: void 0 }; }(); if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v; } // capture namespaces in case of later export if (n.type === 'ImportDeclaration') { var ns = void 0; if (n.specifiers.some(function (s) { return s.type === 'ImportNamespaceSpecifier' && (ns = s); })) { namespaces.set(ns.local.name, n); } return; } if (n.type === 'ExportNamedDeclaration') { // capture declaration if (n.declaration != null) { switch (n.declaration.type) { case 'FunctionDeclaration': case 'ClassDeclaration': case 'TypeAlias': // flowtype with babel-eslint parser m.namespace.set(n.declaration.id.name, captureDoc(n)); break; case 'VariableDeclaration': n.declaration.declarations.forEach(function (d) { return recursivePatternCapture(d.id, function (id) { return m.namespace.set(id.name, captureDoc(d, n)); }); }); break; } } n.specifiers.forEach(function (s) { var exportMeta = {}; var local = void 0; switch (s.type) { case 'ExportDefaultSpecifier': if (!n.source) return; local = 'default'; break; case 'ExportNamespaceSpecifier': m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', { get: function get() { return resolveImport(n); } })); return; case 'ExportSpecifier': if (!n.source) { m.namespace.set(s.exported.name, addNamespace(exportMeta, s.local)); return; } // else falls through default: local = s.local.name; break; } // todo: JSDoc m.reexports.set(s.exported.name, { local: local, getImport: function getImport() { return resolveImport(n); } }); }); } }); return m; }; /** * Note that this does not check explicitly re-exported names for existence * in the base namespace, but it will expand all `export * from '...'` exports * if not found in the explicit namespace. * @param {string} name * @return {Boolean} true if `name` is exported by this module. */ ExportMap.prototype.has = function has(name) { if (this.namespace.has(name)) return true; if (this.reexports.has(name)) return true; // default exports must be explicitly re-exported (#328) if (name !== 'default') { for (var _iterator = this.dependencies.values(), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { var _ref; if (_isArray) { if (_i >= _iterator.length) break; _ref = _iterator[_i++]; } else { _i = _iterator.next(); if (_i.done) break; _ref = _i.value; } var dep = _ref; var innerMap = dep(); // todo: report as unresolved? if (!innerMap) continue; if (innerMap.has(name)) return true; } } return false; }; /** * ensure that imported name fully resolves. * @param {[type]} name [description] * @return {Boolean} [description] */ ExportMap.prototype.hasDeep = function hasDeep(name) { if (this.namespace.has(name)) return { found: true, path: [this] }; if (this.reexports.has(name)) { var _reexports$get = this.reexports.get(name); var local = _reexports$get.local; var getImport = _reexports$get.getImport; var imported = getImport(); // if import is ignored, return explicit 'null' if (imported == null) return { found: true, path: [this] }; // safeguard against cycles, only if name matches if (imported.path === this.path && local === name) return { found: false, path: [this] }; var deep = imported.hasDeep(local); deep.path.unshift(this); return deep; } // default exports must be explicitly re-exported (#328) if (name !== 'default') { for (var _iterator2 = this.dependencies.values(), _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { var _ref2; if (_isArray2) { if (_i2 >= _iterator2.length) break; _ref2 = _iterator2[_i2++]; } else { _i2 = _iterator2.next(); if (_i2.done) break; _ref2 = _i2.value; } var dep = _ref2; var innerMap = dep(); // todo: report as unresolved? if (!innerMap) continue; // safeguard against cycles if (innerMap.path === this.path) continue; var innerValue = innerMap.hasDeep(name); if (innerValue.found) { innerValue.path.unshift(this); return innerValue; } } } return { found: false, path: [this] }; }; ExportMap.prototype.get = function get(name) { if (this.namespace.has(name)) return this.namespace.get(name); if (this.reexports.has(name)) { var _reexports$get2 = this.reexports.get(name); var local = _reexports$get2.local; var getImport = _reexports$get2.getImport; var imported = getImport(); // if import is ignored, return explicit 'null' if (imported == null) return null; // safeguard against cycles, only if name matches if (imported.path === this.path && local === name) return undefined; return imported.get(local); } // default exports must be explicitly re-exported (#328) if (name !== 'default') { for (var _iterator3 = this.dependencies.values(), _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { var _ref3; if (_isArray3) { if (_i3 >= _iterator3.length) break; _ref3 = _iterator3[_i3++]; } else { _i3 = _iterator3.next(); if (_i3.done) break; _ref3 = _i3.value; } var dep = _ref3; var innerMap = dep(); // todo: report as unresolved? if (!innerMap) continue; // safeguard against cycles if (innerMap.path === this.path) continue; var innerValue = innerMap.get(name); if (innerValue !== undefined) return innerValue; } } return undefined; }; ExportMap.prototype.forEach = function forEach(callback, thisArg) { var _this = this; this.namespace.forEach(function (v, n) { return callback.call(thisArg, v, n, _this); }); this.reexports.forEach(function (_ref4, name) { var getImport = _ref4.getImport; var local = _ref4.local; return callback.call(thisArg, getImport().get(local), name, _this); }); this.dependencies.forEach(function (dep) { return dep().forEach(function (v, n) { return n !== 'default' && callback.call(thisArg, v, n, _this); }); }); }; // todo: keys, values, entries? ExportMap.prototype.reportErrors = function reportErrors(context, declaration) { context.report({ node: declaration.source, message: 'Parse errors in imported module \'' + declaration.source.value + '\': ' + ('' + this.errors.map(function (e) { return e.message + ' (' + e.lineNumber + ':' + e.column + ')'; }).join(', ')) }); }; _createClass(ExportMap, [{ key: 'hasDefault', get: function get() { return this.get('default') != null; } // stronger than this.has }, { key: 'size', get: function get() { var size = this.namespace.size + this.reexports.size; this.dependencies.forEach(function (dep) { return size += dep().size; }); return size; } }]); return ExportMap; }(); /** * parse JSDoc from the first node that has leading comments * @param {...[type]} nodes [description] * @return {{doc: object}} */ exports.default = ExportMap; function captureDoc() { var metadata = {}; // 'some' short-circuits on first 'true' for (var _len = arguments.length, nodes = Array(_len), _key = 0; _key < _len; _key++) { nodes[_key] = arguments[_key]; } nodes.some(function (n) { if (!n.leadingComments) return false; // capture XSDoc n.leadingComments.forEach(function (comment) { // skip non-block comments if (comment.value.slice(0, 4) !== '*\n *') return; try { metadata.doc = doctrine.parse(comment.value, { unwrap: true }); } catch (err) { /* don't care, for now? maybe add to `errors?` */ } }); return true; }); return metadata; } /** * Traverse a pattern/identifier node, calling 'callback' * for each leaf identifier. * @param {node} pattern * @param {Function} callback * @return {void} */ function recursivePatternCapture(pattern, callback) { switch (pattern.type) { case 'Identifier': // base case callback(pattern); break; case 'ObjectPattern': pattern.properties.forEach(function (_ref5) { var value = _ref5.value; recursivePatternCapture(value, callback); }); break; case 'ArrayPattern': pattern.elements.forEach(function (element) { if (element == null) return; recursivePatternCapture(element, callback); }); break; } } //# sourceMappingURL=data:application/json;base64,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YixDQUF6QixDQURGO0FBS0UsWUFMRjtBQVhGLEdBRHlEO0NBQXBEIiwiZmlsZSI6ImNvcmUvZ2V0RXhwb3J0cy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAnZXM2LXN5bWJvbC9pbXBsZW1lbnQnXG5pbXBvcnQgTWFwIGZyb20gJ2VzNi1tYXAnXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJ1xuXG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnY3J5cHRvJ1xuaW1wb3J0ICogYXMgZG9jdHJpbmUgZnJvbSAnZG9jdHJpbmUnXG5cbmltcG9ydCBwYXJzZSBmcm9tICcuL3BhcnNlJ1xuaW1wb3J0IHJlc29sdmUgZnJvbSAnLi9yZXNvbHZlJ1xuaW1wb3J0IGlzSWdub3JlZCBmcm9tICcuL2lnbm9yZSdcblxuaW1wb3J0IHsgaGFzaE9iamVjdCB9IGZyb20gJy4vaGFzaCdcblxuY29uc3QgZXhwb3J0Q2FjaGUgPSBuZXcgTWFwKClcblxuLyoqXG4gKiBkZXRlY3QgZXhwb3J0cyB3aXRob3V0IGEgZnVsbCBwYXJzZS5cbiAqIHVzZWQgcHJpbWFyaWx5IHRvIGlnbm9yZSB0aGUgaW1wb3J0L2lnbm9yZSBzZXR0aW5nLCBpaWYgaXQgbG9va3MgbGlrZVxuICogdGhlcmUgbWlnaHQgYmUgc29tZXRoaW5nIHRoZXJlIChpLmUuLCBqc25leHQ6bWFpbiBpcyBzZXQpLlxuICogQHR5cGUge1JlZ0V4cH1cbiAqL1xuY29uc3QgaGFzRXhwb3J0cyA9IG5ldyBSZWdFeHAoJyhefFtcXFxcbjtdKVxcXFxzKmV4cG9ydFxcXFxzW1xcXFx3eypdJylcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRXhwb3J0TWFwIHtcbiAgY29uc3RydWN0b3IocGF0aCkge1xuICAgIHRoaXMucGF0aCA9IHBhdGhcbiAgICB0aGlzLm5hbWVzcGFjZSA9IG5ldyBNYXAoKVxuICAgIC8vIHRvZG86IHJlc3RydWN0dXJlIHRvIGtleSBvbiBwYXRoLCB2YWx1ZSBpcyByZXNvbHZlciArIG1hcCBvZiBuYW1lc1xuICAgIHRoaXMucmVleHBvcnRzID0gbmV3IE1hcCgpXG4gICAgdGhpcy5kZXBlbmRlbmNpZXMgPSBuZXcgTWFwKClcbiAgICB0aGlzLmVycm9ycyA9IFtdXG4gIH1cblxuICBnZXQgaGFzRGVmYXVsdCgpIHsgcmV0dXJuIHRoaXMuZ2V0KCdkZWZhdWx0JykgIT0gbnVsbCB9IC8vIHN0cm9uZ2VyIHRoYW4gdGhpcy5oYXNcblxuICBnZXQgc2l6ZSgpIHtcbiAgICBsZXQgc2l6ZSA9IHRoaXMubmFtZXNwYWNlLnNpemUgKyB0aGlzLnJlZXhwb3J0cy5zaXplXG4gICAgdGhpcy5kZXBlbmRlbmNpZXMuZm9yRWFjaChkZXAgPT4gc2l6ZSArPSBkZXAoKS5zaXplKVxuICAgIHJldHVybiBzaXplXG4gIH1cblxuICBzdGF0aWMgZ2V0KHNvdXJjZSwgY29udGV4dCkge1xuXG4gICAgdmFyIHBhdGggPSByZXNvbHZlKHNvdXJjZSwgY29udGV4dClcbiAgICBpZiAocGF0aCA9PSBudWxsKSByZXR1cm4gbnVsbFxuXG4gICAgcmV0dXJuIEV4cG9ydE1hcC5mb3IocGF0aCwgY29udGV4dClcbiAgfVxuXG4gIHN0YXRpYyBmb3IocGF0aCwgY29udGV4dCkge1xuICAgIGxldCBleHBvcnRNYXBcblxuICAgIGNvbnN0IGNhY2hlS2V5ID0gaGFzaE9iamVjdChjcmVhdGVIYXNoKCdzaGEyNTYnKSwge1xuICAgICAgc2V0dGluZ3M6IGNvbnRleHQuc2V0dGluZ3MsXG4gICAgICBwYXJzZXJQYXRoOiBjb250ZXh0LnBhcnNlclBhdGgsXG4gICAgICBwYXJzZXJPcHRpb25zOiBjb250ZXh0LnBhcnNlck9wdGlvbnMsXG4gICAgICBwYXRoLFxuICAgIH0pLmRpZ2VzdCgnaGV4JylcblxuICAgIGV4cG9ydE1hcCA9IGV4cG9ydENhY2hlLmdldChjYWNoZUtleSlcblxuICAgIC8vIHJldHVybiBjYWNoZWQgaWdub3JlXG4gICAgaWYgKGV4cG9ydE1hcCA9PT0gbnVsbCkgcmV0dXJuIG51bGxcblxuICAgIGNvbnN0IHN0YXRzID0gZnMuc3RhdFN5bmMocGF0aClcbiAgICBpZiAoZXhwb3J0TWFwICE9IG51bGwpIHtcbiAgICAgIC8vIGRhdGUgZXF1YWxpdHkgY2hlY2tcbiAgICAgIGlmIChleHBvcnRNYXAubXRpbWUgLSBzdGF0cy5tdGltZSA9PT0gMCkge1xuICAgICAgICByZXR1cm4gZXhwb3J0TWFwXG4gICAgICB9XG4gICAgICAvLyBmdXR1cmU6IGNoZWNrIGNvbnRlbnQgZXF1YWxpdHk/XG4gICAgfVxuXG4gICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhwYXRoLCB7IGVuY29kaW5nOiAndXRmOCcgfSlcblxuICAgIC8vIGNoZWNrIGZvciBhbmQgY2FjaGUgaWdub3JlXG4gICAgaWYgKGlzSWdub3JlZChwYXRoLCBjb250ZXh0KSAmJiAhaGFzRXhwb3J0cy50ZXN0KGNvbnRlbnQpKSB7XG4gICAgICBleHBvcnRDYWNoZS5zZXQoY2FjaGVLZXksIG51bGwpXG4gICAgICByZXR1cm4gbnVsbFxuICAgIH1cblxuICAgIGV4cG9ydE1hcCA9IEV4cG9ydE1hcC5wYXJzZShwYXRoLCBjb250ZW50LCBjb250ZXh0KVxuICAgIGV4cG9ydE1hcC5tdGltZSA9IHN0YXRzLm10aW1lXG5cbiAgICBleHBvcnRDYWNoZS5zZXQoY2FjaGVLZXksIGV4cG9ydE1hcClcbiAgICByZXR1cm4gZXhwb3J0TWFwXG4gIH1cblxuICBzdGF0aWMgcGFyc2UocGF0aCwgY29udGVudCwgY29udGV4dCkge1xuICAgIHZhciBtID0gbmV3IEV4cG9ydE1hcChwYXRoKVxuXG4gICAgdHJ5IHtcbiAgICAgIHZhciBhc3QgPSBwYXJzZShjb250ZW50LCBjb250ZXh0KVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbS5lcnJvcnMucHVzaChlcnIpXG4gICAgICByZXR1cm4gbSAvLyBjYW4ndCBjb250aW51ZVxuICAgIH1cblxuICAgIC8vIGF0dGVtcHQgdG8gY29sbGVjdCBtb2R1bGUgZG9jXG4gICAgYXN0LmNvbW1lbnRzLnNvbWUoYyA9PiB7XG4gICAgICBpZiAoYy50eXBlICE9PSAnQmxvY2snKSByZXR1cm4gZmFsc2VcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGRvYyA9IGRvY3RyaW5lLnBhcnNlKGMudmFsdWUsIHsgdW53cmFwOiB0cnVlIH0pXG4gICAgICAgIGlmIChkb2MudGFncy5zb21lKHQgPT4gdC50aXRsZSA9PT0gJ21vZHVsZScpKSB7XG4gICAgICAgICAgbS5kb2MgPSBkb2NcbiAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnIpIHsgLyogaWdub3JlICovIH1cbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH0pXG5cbiAgICBjb25zdCBuYW1lc3BhY2VzID0gbmV3IE1hcCgpXG5cbiAgICBmdW5jdGlvbiByZW1vdGVQYXRoKG5vZGUpIHtcbiAgICAgIHJldHVybiByZXNvbHZlLnJlbGF0aXZlKG5vZGUuc291cmNlLnZhbHVlLCBwYXRoLCBjb250ZXh0LnNldHRpbmdzKVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlc29sdmVJbXBvcnQobm9kZSkge1xuICAgICAgY29uc3QgcnAgPSByZW1vdGVQYXRoKG5vZGUpXG4gICAgICBpZiAocnAgPT0gbnVsbCkgcmV0dXJuIG51bGxcbiAgICAgIHJldHVybiBFeHBvcnRNYXAuZm9yKHJwLCBjb250ZXh0KVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldE5hbWVzcGFjZShpZGVudGlmaWVyKSB7XG4gICAgICBpZiAoIW5hbWVzcGFjZXMuaGFzKGlkZW50aWZpZXIubmFtZSkpIHJldHVyblxuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcmVzb2x2ZUltcG9ydChuYW1lc3BhY2VzLmdldChpZGVudGlmaWVyLm5hbWUpKVxuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZE5hbWVzcGFjZShvYmplY3QsIGlkZW50aWZpZXIpIHtcbiAgICAgIGNvbnN0IG5zZm4gPSBnZXROYW1lc3BhY2UoaWRlbnRpZmllcilcbiAgICAgIGlmIChuc2ZuKSB7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmplY3QsICduYW1lc3BhY2UnLCB7IGdldDogbnNmbiB9KVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gb2JqZWN0XG4gICAgfVxuXG5cbiAgICBhc3QuYm9keS5mb3JFYWNoKGZ1bmN0aW9uIChuKSB7XG5cbiAgICAgIGlmIChuLnR5cGUgPT09ICdFeHBvcnREZWZhdWx0RGVjbGFyYXRpb24nKSB7XG4gICAgICAgIGNvbnN0IGV4cG9ydE1ldGEgPSBjYXB0dXJlRG9jKG4pXG4gICAgICAgIGlmIChuLmRlY2xhcmF0aW9uLnR5cGUgPT09ICdJZGVudGlmaWVyJykge1xuICAgICAgICAgIGFkZE5hbWVzcGFjZShleHBvcnRNZXRhLCBuLmRlY2xhcmF0aW9uKVxuICAgICAgICB9XG4gICAgICAgIG0ubmFtZXNwYWNlLnNldCgnZGVmYXVsdCcsIGV4cG9ydE1ldGEpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBpZiAobi50eXBlID09PSAnRXhwb3J0QWxsRGVjbGFyYXRpb24nKSB7XG4gICAgICAgIGxldCByZW1vdGVNYXAgPSByZW1vdGVQYXRoKG4pXG4gICAgICAgIGlmIChyZW1vdGVNYXAgPT0gbnVsbCkgcmV0dXJuXG4gICAgICAgIG0uZGVwZW5kZW5jaWVzLnNldChyZW1vdGVNYXAsICgpID0+IEV4cG9ydE1hcC5mb3IocmVtb3RlTWFwLCBjb250ZXh0KSlcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIC8vIGNhcHR1cmUgbmFtZXNwYWNlcyBpbiBjYXNlIG9mIGxhdGVyIGV4cG9ydFxuICAgICAgaWYgKG4udHlwZSA9PT0gJ0ltcG9ydERlY2xhcmF0aW9uJykge1xuICAgICAgICBsZXQgbnNcbiAgICAgICAgaWYgKG4uc3BlY2lmaWVycy5zb21lKHMgPT4gcy50eXBlID09PSAnSW1wb3J0TmFtZXNwYWNlU3BlY2lmaWVyJyAmJiAobnMgPSBzKSkpIHtcbiAgICAgICAgICBuYW1lc3BhY2VzLnNldChucy5sb2NhbC5uYW1lLCBuKVxuICAgICAgICB9XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBpZiAobi50eXBlID09PSAnRXhwb3J0TmFtZWREZWNsYXJhdGlvbicpe1xuICAgICAgICAvLyBjYXB0dXJlIGRlY2xhcmF0aW9uXG4gICAgICAgIGlmIChuLmRlY2xhcmF0aW9uICE9IG51bGwpIHtcbiAgICAgICAgICBzd2l0Y2ggKG4uZGVjbGFyYXRpb24udHlwZSkge1xuICAgICAgICAgICAgY2FzZSAnRnVuY3Rpb25EZWNsYXJhdGlvbic6XG4gICAgICAgICAgICBjYXNlICdDbGFzc0RlY2xhcmF0aW9uJzpcbiAgICAgICAgICAgIGNhc2UgJ1R5cGVBbGlhcyc6IC8vIGZsb3d0eXBlIHdpdGggYmFiZWwtZXNsaW50IHBhcnNlclxuICAgICAgICAgICAgICBtLm5hbWVzcGFjZS5zZXQobi5kZWNsYXJhdGlvbi5pZC5uYW1lLCBjYXB0dXJlRG9jKG4pKVxuICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgY2FzZSAnVmFyaWFibGVEZWNsYXJhdGlvbic6XG4gICAgICAgICAgICAgIG4uZGVjbGFyYXRpb24uZGVjbGFyYXRpb25zLmZvckVhY2goKGQpID0+XG4gICAgICAgICAgICAgICAgcmVjdXJzaXZlUGF0dGVybkNhcHR1cmUoZC5pZCwgaWQgPT4gbS5uYW1lc3BhY2Uuc2V0KGlkLm5hbWUsIGNhcHR1cmVEb2MoZCwgbikpKSlcbiAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBuLnNwZWNpZmllcnMuZm9yRWFjaCgocykgPT4ge1xuICAgICAgICAgIGNvbnN0IGV4cG9ydE1ldGEgPSB7fVxuICAgICAgICAgIGxldCBsb2NhbFxuXG4gICAgICAgICAgc3dpdGNoIChzLnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ0V4cG9ydERlZmF1bHRTcGVjaWZpZXInOlxuICAgICAgICAgICAgICBpZiAoIW4uc291cmNlKSByZXR1cm5cbiAgICAgICAgICAgICAgbG9jYWwgPSAnZGVmYXVsdCdcbiAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgIGNhc2UgJ0V4cG9ydE5hbWVzcGFjZVNwZWNpZmllcic6XG4gICAgICAgICAgICAgIG0ubmFtZXNwYWNlLnNldChzLmV4cG9ydGVkLm5hbWUsIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRNZXRhLCAnbmFtZXNwYWNlJywge1xuICAgICAgICAgICAgICAgIGdldCgpIHsgcmV0dXJuIHJlc29sdmVJbXBvcnQobikgfSxcbiAgICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgY2FzZSAnRXhwb3J0U3BlY2lmaWVyJzpcbiAgICAgICAgICAgICAgaWYgKCFuLnNvdXJjZSkge1xuICAgICAgICAgICAgICAgIG0ubmFtZXNwYWNlLnNldChzLmV4cG9ydGVkLm5hbWUsIGFkZE5hbWVzcGFjZShleHBvcnRNZXRhLCBzLmxvY2FsKSlcbiAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAvLyBlbHNlIGZhbGxzIHRocm91Z2hcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIGxvY2FsID0gcy5sb2NhbC5uYW1lXG4gICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gdG9kbzogSlNEb2NcbiAgICAgICAgICBtLnJlZXhwb3J0cy5zZXQocy5leHBvcnRlZC5uYW1lLCB7IGxvY2FsLCBnZXRJbXBvcnQ6ICgpID0+IHJlc29sdmVJbXBvcnQobikgfSlcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICB9KVxuXG4gICAgcmV0dXJuIG1cbiAgfVxuXG4gIC8qKlxuICAgKiBOb3RlIHRoYXQgdGhpcyBkb2VzIG5vdCBjaGVjayBleHBsaWNpdGx5IHJlLWV4cG9ydGVkIG5hbWVzIGZvciBleGlzdGVuY2VcbiAgICogaW4gdGhlIGJhc2UgbmFtZXNwYWNlLCBidXQgaXQgd2lsbCBleHBhbmQgYWxsIGBleHBvcnQgKiBmcm9tICcuLi4nYCBleHBvcnRzXG4gICAqIGlmIG5vdCBmb3VuZCBpbiB0aGUgZXhwbGljaXQgbmFtZXNwYWNlLlxuICAgKiBAcGFyYW0gIHtzdHJpbmd9ICBuYW1lXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWUgaWYgYG5hbWVgIGlzIGV4cG9ydGVkIGJ5IHRoaXMgbW9kdWxlLlxuICAgKi9cbiAgaGFzKG5hbWUpIHtcbiAgICBpZiAodGhpcy5uYW1lc3BhY2UuaGFzKG5hbWUpKSByZXR1cm4gdHJ1ZVxuICAgIGlmICh0aGlzLnJlZXhwb3J0cy5oYXMobmFtZSkpIHJldHVybiB0cnVlXG5cbiAgICAvLyBkZWZhdWx0IGV4cG9ydHMgbXVzdCBiZSBleHBsaWNpdGx5IHJlLWV4cG9ydGVkICgjMzI4KVxuICAgIGlmIChuYW1lICE9PSAnZGVmYXVsdCcpIHtcbiAgICAgIGZvciAobGV0IGRlcCBvZiB0aGlzLmRlcGVuZGVuY2llcy52YWx1ZXMoKSkge1xuICAgICAgICBsZXQgaW5uZXJNYXAgPSBkZXAoKVxuXG4gICAgICAgIC8vIHRvZG86IHJlcG9ydCBhcyB1bnJlc29sdmVkP1xuICAgICAgICBpZiAoIWlubmVyTWFwKSBjb250aW51ZVxuXG4gICAgICAgIGlmIChpbm5lck1hcC5oYXMobmFtZSkpIHJldHVybiB0cnVlXG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogZW5zdXJlIHRoYXQgaW1wb3J0ZWQgbmFtZSBmdWxseSByZXNvbHZlcy5cbiAgICogQHBhcmFtICB7W3R5cGVdfSAgbmFtZSBbZGVzY3JpcHRpb25dXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59ICAgICAgW2Rlc2NyaXB0aW9uXVxuICAgKi9cbiAgaGFzRGVlcChuYW1lKSB7XG4gICAgaWYgKHRoaXMubmFtZXNwYWNlLmhhcyhuYW1lKSkgcmV0dXJuIHsgZm91bmQ6IHRydWUsIHBhdGg6IFt0aGlzXSB9XG5cbiAgICBpZiAodGhpcy5yZWV4cG9ydHMuaGFzKG5hbWUpKSB7XG4gICAgICBjb25zdCB7IGxvY2FsLCBnZXRJbXBvcnQgfSA9IHRoaXMucmVleHBvcnRzLmdldChuYW1lKVxuICAgICAgICAgICwgaW1wb3J0ZWQgPSBnZXRJbXBvcnQoKVxuXG4gICAgICAvLyBpZiBpbXBvcnQgaXMgaWdub3JlZCwgcmV0dXJuIGV4cGxpY2l0ICdudWxsJ1xuICAgICAgaWYgKGltcG9ydGVkID09IG51bGwpIHJldHVybiB7IGZvdW5kOiB0cnVlLCBwYXRoOiBbdGhpc10gfVxuXG4gICAgICAvLyBzYWZlZ3VhcmQgYWdhaW5zdCBjeWNsZXMsIG9ubHkgaWYgbmFtZSBtYXRjaGVzXG4gICAgICBpZiAoaW1wb3J0ZWQucGF0aCA9PT0gdGhpcy5wYXRoICYmIGxvY2FsID09PSBuYW1lKSByZXR1cm4geyBmb3VuZDogZmFsc2UsIHBhdGg6IFt0aGlzXSB9XG5cbiAgICAgIGNvbnN0IGRlZXAgPSBpbXBvcnRlZC5oYXNEZWVwKGxvY2FsKVxuICAgICAgZGVlcC5wYXRoLnVuc2hpZnQodGhpcylcblxuICAgICAgcmV0dXJuIGRlZXBcbiAgICB9XG5cblxuICAgIC8vIGRlZmF1bHQgZXhwb3J0cyBtdXN0IGJlIGV4cGxpY2l0bHkgcmUtZXhwb3J0ZWQgKCMzMjgpXG4gICAgaWYgKG5hbWUgIT09ICdkZWZhdWx0Jykge1xuICAgICAgZm9yIChsZXQgZGVwIG9mIHRoaXMuZGVwZW5kZW5jaWVzLnZhbHVlcygpKSB7XG4gICAgICAgIGxldCBpbm5lck1hcCA9IGRlcCgpXG4gICAgICAgIC8vIHRvZG86IHJlcG9ydCBhcyB1bnJlc29sdmVkP1xuICAgICAgICBpZiAoIWlubmVyTWFwKSBjb250aW51ZVxuXG4gICAgICAgIC8vIHNhZmVndWFyZCBhZ2FpbnN0IGN5Y2xlc1xuICAgICAgICBpZiAoaW5uZXJNYXAucGF0aCA9PT0gdGhpcy5wYXRoKSBjb250aW51ZVxuXG4gICAgICAgIGxldCBpbm5lclZhbHVlID0gaW5uZXJNYXAuaGFzRGVlcChuYW1lKVxuICAgICAgICBpZiAoaW5uZXJWYWx1ZS5mb3VuZCkge1xuICAgICAgICAgIGlubmVyVmFsdWUucGF0aC51bnNoaWZ0KHRoaXMpXG4gICAgICAgICAgcmV0dXJuIGlubmVyVmFsdWVcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7IGZvdW5kOiBmYWxzZSwgcGF0aDogW3RoaXNdIH1cbiAgfVxuXG4gIGdldChuYW1lKSB7XG4gICAgaWYgKHRoaXMubmFtZXNwYWNlLmhhcyhuYW1lKSkgcmV0dXJuIHRoaXMubmFtZXNwYWNlLmdldChuYW1lKVxuXG4gICAgaWYgKHRoaXMucmVleHBvcnRzLmhhcyhuYW1lKSkge1xuICAgICAgY29uc3QgeyBsb2NhbCwgZ2V0SW1wb3J0IH0gPSB0aGlzLnJlZXhwb3J0cy5nZXQobmFtZSlcbiAgICAgICAgICAsIGltcG9ydGVkID0gZ2V0SW1wb3J0KClcblxuICAgICAgLy8gaWYgaW1wb3J0IGlzIGlnbm9yZWQsIHJldHVybiBleHBsaWNpdCAnbnVsbCdcbiAgICAgIGlmIChpbXBvcnRlZCA9PSBudWxsKSByZXR1cm4gbnVsbFxuXG4gICAgICAvLyBzYWZlZ3VhcmQgYWdhaW5zdCBjeWNsZXMsIG9ubHkgaWYgbmFtZSBtYXRjaGVzXG4gICAgICBpZiAoaW1wb3J0ZWQucGF0aCA9PT0gdGhpcy5wYXRoICYmIGxvY2FsID09PSBuYW1lKSByZXR1cm4gdW5kZWZpbmVkXG5cbiAgICAgIHJldHVybiBpbXBvcnRlZC5nZXQobG9jYWwpXG4gICAgfVxuXG4gICAgLy8gZGVmYXVsdCBleHBvcnRzIG11c3QgYmUgZXhwbGljaXRseSByZS1leHBvcnRlZCAoIzMyOClcbiAgICBpZiAobmFtZSAhPT0gJ2RlZmF1bHQnKSB7XG4gICAgICBmb3IgKGxldCBkZXAgb2YgdGhpcy5kZXBlbmRlbmNpZXMudmFsdWVzKCkpIHtcbiAgICAgICAgbGV0IGlubmVyTWFwID0gZGVwKClcbiAgICAgICAgLy8gdG9kbzogcmVwb3J0IGFzIHVucmVzb2x2ZWQ/XG4gICAgICAgIGlmICghaW5uZXJNYXApIGNvbnRpbnVlXG5cbiAgICAgICAgLy8gc2FmZWd1YXJkIGFnYWluc3QgY3ljbGVzXG4gICAgICAgIGlmIChpbm5lck1hcC5wYXRoID09PSB0aGlzLnBhdGgpIGNvbnRpbnVlXG5cbiAgICAgICAgbGV0IGlubmVyVmFsdWUgPSBpbm5lck1hcC5nZXQobmFtZSlcbiAgICAgICAgaWYgKGlubmVyVmFsdWUgIT09IHVuZGVmaW5lZCkgcmV0dXJuIGlubmVyVmFsdWVcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH1cblxuICBmb3JFYWNoKGNhbGxiYWNrLCB0aGlzQXJnKSB7XG4gICAgdGhpcy5uYW1lc3BhY2UuZm9yRWFjaCgodiwgbikgPT5cbiAgICAgIGNhbGxiYWNrLmNhbGwodGhpc0FyZywgdiwgbiwgdGhpcykpXG5cbiAgICB0aGlzLnJlZXhwb3J0cy5mb3JFYWNoKCh7IGdldEltcG9ydCwgbG9jYWwgfSwgbmFtZSkgPT5cbiAgICAgIGNhbGxiYWNrLmNhbGwodGhpc0FyZywgZ2V0SW1wb3J0KCkuZ2V0KGxvY2FsKSwgbmFtZSwgdGhpcykpXG5cbiAgICB0aGlzLmRlcGVuZGVuY2llcy5mb3JFYWNoKGRlcCA9PiBkZXAoKS5mb3JFYWNoKCh2LCBuKSA9PlxuICAgICAgbiAhPT0gJ2RlZmF1bHQnICYmIGNhbGxiYWNrLmNhbGwodGhpc0FyZywgdiwgbiwgdGhpcykpKVxuICB9XG5cbiAgLy8gdG9kbzoga2V5cywgdmFsdWVzLCBlbnRyaWVzP1xuXG4gIHJlcG9ydEVycm9ycyhjb250ZXh0LCBkZWNsYXJhdGlvbikge1xuICAgIGNvbnRleHQucmVwb3J0KHtcbiAgICAgIG5vZGU6IGRlY2xhcmF0aW9uLnNvdXJjZSxcbiAgICAgIG1lc3NhZ2U6IGBQYXJzZSBlcnJvcnMgaW4gaW1wb3J0ZWQgbW9kdWxlICcke2RlY2xhcmF0aW9uLnNvdXJjZS52YWx1ZX0nOiBgICtcbiAgICAgICAgICAgICAgICAgIGAke3RoaXMuZXJyb3JzXG4gICAgICAgICAgICAgICAgICAgICAgICAubWFwKGUgPT4gYCR7ZS5tZXNzYWdlfSAoJHtlLmxpbmVOdW1iZXJ9OiR7ZS5jb2x1bW59KWApXG4gICAgICAgICAgICAgICAgICAgICAgICAuam9pbignLCAnKX1gLFxuICAgIH0pXG4gIH1cbn1cblxuLyoqXG4gKiBwYXJzZSBKU0RvYyBmcm9tIHRoZSBmaXJzdCBub2RlIHRoYXQgaGFzIGxlYWRpbmcgY29tbWVudHNcbiAqIEBwYXJhbSAgey4uLlt0eXBlXX0gbm9kZXMgW2Rlc2NyaXB0aW9uXVxuICogQHJldHVybiB7e2RvYzogb2JqZWN0fX1cbiAqL1xuZnVuY3Rpb24gY2FwdHVyZURvYyguLi5ub2Rlcykge1xuICBjb25zdCBtZXRhZGF0YSA9IHt9XG5cbiAgLy8gJ3NvbWUnIHNob3J0LWNpcmN1aXRzIG9uIGZpcnN0ICd0cnVlJ1xuICBub2Rlcy5zb21lKG4gPT4ge1xuICAgIGlmICghbi5sZWFkaW5nQ29tbWVudHMpIHJldHVybiBmYWxzZVxuXG4gICAgLy8gY2FwdHVyZSBYU0RvY1xuICAgIG4ubGVhZGluZ0NvbW1lbnRzLmZvckVhY2goY29tbWVudCA9PiB7XG4gICAgICAvLyBza2lwIG5vbi1ibG9jayBjb21tZW50c1xuICAgICAgaWYgKGNvbW1lbnQudmFsdWUuc2xpY2UoMCwgNCkgIT09ICcqXFxuIConKSByZXR1cm5cbiAgICAgIHRyeSB7XG4gICAgICAgIG1ldGFkYXRhLmRvYyA9IGRvY3RyaW5lLnBhcnNlKGNvbW1lbnQudmFsdWUsIHsgdW53cmFwOiB0cnVlIH0pXG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgLyogZG9uJ3QgY2FyZSwgZm9yIG5vdz8gbWF5YmUgYWRkIHRvIGBlcnJvcnM/YCAqL1xuICAgICAgfVxuICAgIH0pXG4gICAgcmV0dXJuIHRydWVcbiAgfSlcblxuICByZXR1cm4gbWV0YWRhdGFcbn1cblxuLyoqXG4gKiBUcmF2ZXJzZSBhIHBhdHRlcm4vaWRlbnRpZmllciBub2RlLCBjYWxsaW5nICdjYWxsYmFjaydcbiAqIGZvciBlYWNoIGxlYWYgaWRlbnRpZmllci5cbiAqIEBwYXJhbSAge25vZGV9ICAgcGF0dGVyblxuICogQHBhcmFtICB7RnVuY3Rpb259IGNhbGxiYWNrXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVjdXJzaXZlUGF0dGVybkNhcHR1cmUocGF0dGVybiwgY2FsbGJhY2spIHtcbiAgc3dpdGNoIChwYXR0ZXJuLnR5cGUpIHtcbiAgICBjYXNlICdJZGVudGlmaWVyJzogLy8gYmFzZSBjYXNlXG4gICAgICBjYWxsYmFjayhwYXR0ZXJuKVxuICAgICAgYnJlYWtcblxuICAgIGNhc2UgJ09iamVjdFBhdHRlcm4nOlxuICAgICAgcGF0dGVybi5wcm9wZXJ0aWVzLmZvckVhY2goKHsgdmFsdWUgfSkgPT4ge1xuICAgICAgICByZWN1cnNpdmVQYXR0ZXJuQ2FwdHVyZSh2YWx1ZSwgY2FsbGJhY2spXG4gICAgICB9KVxuICAgICAgYnJlYWtcblxuICAgIGNhc2UgJ0FycmF5UGF0dGVybic6XG4gICAgICBwYXR0ZXJuLmVsZW1lbnRzLmZvckVhY2goKGVsZW1lbnQpID0+IHtcbiAgICAgICAgaWYgKGVsZW1lbnQgPT0gbnVsbCkgcmV0dXJuXG4gICAgICAgIHJlY3Vyc2l2ZVBhdHRlcm5DYXB0dXJlKGVsZW1lbnQsIGNhbGxiYWNrKVxuICAgICAgfSlcbiAgICAgIGJyZWFrXG4gIH1cbn1cbiJdfQ==