366 lines
56 KiB
JavaScript
366 lines
56 KiB
JavaScript
|
'use strict';var _slicedToArray = function () {function sliceIterator(arr, i) {var _arr = [];var _n = true;var _d = false;var _e = undefined;try {for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {_arr.push(_s.value);if (i && _arr.length === i) break;}} catch (err) {_d = true;_e = err;} finally {try {if (!_n && _i["return"]) _i["return"]();} finally {if (_d) throw _e;}}return _arr;}return function (arr, i) {if (Array.isArray(arr)) {return arr;} else if (Symbol.iterator in Object(arr)) {return sliceIterator(arr, i);} else {throw new TypeError("Invalid attempt to destructure non-iterable instance");}};}();var _resolve = require('eslint-module-utils/resolve');var _resolve2 = _interopRequireDefault(_resolve);
|
|||
|
var _semver = require('semver');var _semver2 = _interopRequireDefault(_semver);
|
|||
|
var _arrayPrototype = require('array.prototype.flatmap');var _arrayPrototype2 = _interopRequireDefault(_arrayPrototype);
|
|||
|
|
|||
|
var _docsUrl = require('../docsUrl');var _docsUrl2 = _interopRequireDefault(_docsUrl);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { 'default': obj };}function _toArray(arr) {return Array.isArray(arr) ? arr : Array.from(arr);}
|
|||
|
|
|||
|
var typescriptPkg = void 0;
|
|||
|
try {
|
|||
|
typescriptPkg = require('typescript/package.json'); // eslint-disable-line import/no-extraneous-dependencies
|
|||
|
} catch (e) {/**/}
|
|||
|
|
|||
|
function isPunctuator(node, value) {
|
|||
|
return node.type === 'Punctuator' && node.value === value;
|
|||
|
}
|
|||
|
|
|||
|
// Get the name of the default import of `node`, if any.
|
|||
|
function getDefaultImportName(node) {
|
|||
|
var defaultSpecifier = node.specifiers.
|
|||
|
find(function (specifier) {return specifier.type === 'ImportDefaultSpecifier';});
|
|||
|
return defaultSpecifier != null ? defaultSpecifier.local.name : undefined;
|
|||
|
}
|
|||
|
|
|||
|
// Checks whether `node` has a namespace import.
|
|||
|
function hasNamespace(node) {
|
|||
|
var specifiers = node.specifiers.
|
|||
|
filter(function (specifier) {return specifier.type === 'ImportNamespaceSpecifier';});
|
|||
|
return specifiers.length > 0;
|
|||
|
}
|
|||
|
|
|||
|
// Checks whether `node` has any non-default specifiers.
|
|||
|
function hasSpecifiers(node) {
|
|||
|
var specifiers = node.specifiers.
|
|||
|
filter(function (specifier) {return specifier.type === 'ImportSpecifier';});
|
|||
|
return specifiers.length > 0;
|
|||
|
}
|
|||
|
|
|||
|
// Checks whether `node` has a comment (that ends) on the previous line or on
|
|||
|
// the same line as `node` (starts).
|
|||
|
function hasCommentBefore(node, sourceCode) {
|
|||
|
return sourceCode.getCommentsBefore(node).
|
|||
|
some(function (comment) {return comment.loc.end.line >= node.loc.start.line - 1;});
|
|||
|
}
|
|||
|
|
|||
|
// Checks whether `node` has a comment (that starts) on the same line as `node`
|
|||
|
// (ends).
|
|||
|
function hasCommentAfter(node, sourceCode) {
|
|||
|
return sourceCode.getCommentsAfter(node).
|
|||
|
some(function (comment) {return comment.loc.start.line === node.loc.end.line;});
|
|||
|
}
|
|||
|
|
|||
|
// Checks whether `node` has any comments _inside,_ except inside the `{...}`
|
|||
|
// part (if any).
|
|||
|
function hasCommentInsideNonSpecifiers(node, sourceCode) {
|
|||
|
var tokens = sourceCode.getTokens(node);
|
|||
|
var openBraceIndex = tokens.findIndex(function (token) {return isPunctuator(token, '{');});
|
|||
|
var closeBraceIndex = tokens.findIndex(function (token) {return isPunctuator(token, '}');});
|
|||
|
// Slice away the first token, since we're no looking for comments _before_
|
|||
|
// `node` (only inside). If there's a `{...}` part, look for comments before
|
|||
|
// the `{`, but not before the `}` (hence the `+1`s).
|
|||
|
var someTokens = openBraceIndex >= 0 && closeBraceIndex >= 0 ?
|
|||
|
tokens.slice(1, openBraceIndex + 1).concat(tokens.slice(closeBraceIndex + 1)) :
|
|||
|
tokens.slice(1);
|
|||
|
return someTokens.some(function (token) {return sourceCode.getCommentsBefore(token).length > 0;});
|
|||
|
}
|
|||
|
|
|||
|
// It's not obvious what the user wants to do with comments associated with
|
|||
|
// duplicate imports, so skip imports with comments when autofixing.
|
|||
|
function hasProblematicComments(node, sourceCode) {
|
|||
|
return (
|
|||
|
hasCommentBefore(node, sourceCode) ||
|
|||
|
hasCommentAfter(node, sourceCode) ||
|
|||
|
hasCommentInsideNonSpecifiers(node, sourceCode));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
function getFix(first, rest, sourceCode, context) {
|
|||
|
// Sorry ESLint <= 3 users, no autofix for you. Autofixing duplicate imports
|
|||
|
// requires multiple `fixer.whatever()` calls in the `fix`: We both need to
|
|||
|
// update the first one, and remove the rest. Support for multiple
|
|||
|
// `fixer.whatever()` in a single `fix` was added in ESLint 4.1.
|
|||
|
// `sourceCode.getCommentsBefore` was added in 4.0, so that's an easy thing to
|
|||
|
// check for.
|
|||
|
if (typeof sourceCode.getCommentsBefore !== 'function') {
|
|||
|
return undefined;
|
|||
|
}
|
|||
|
|
|||
|
// Adjusting the first import might make it multiline, which could break
|
|||
|
// `eslint-disable-next-line` comments and similar, so bail if the first
|
|||
|
// import has comments. Also, if the first import is `import * as ns from
|
|||
|
// './foo'` there's nothing we can do.
|
|||
|
if (hasProblematicComments(first, sourceCode) || hasNamespace(first)) {
|
|||
|
return undefined;
|
|||
|
}
|
|||
|
|
|||
|
var defaultImportNames = new Set(
|
|||
|
(0, _arrayPrototype2['default'])([].concat(first, rest || []), function (x) {return getDefaultImportName(x) || [];}));
|
|||
|
|
|||
|
|
|||
|
// Bail if there are multiple different default import names – it's up to the
|
|||
|
// user to choose which one to keep.
|
|||
|
if (defaultImportNames.size > 1) {
|
|||
|
return undefined;
|
|||
|
}
|
|||
|
|
|||
|
// Leave it to the user to handle comments. Also skip `import * as ns from
|
|||
|
// './foo'` imports, since they cannot be merged into another import.
|
|||
|
var restWithoutComments = rest.filter(function (node) {return !hasProblematicComments(node, sourceCode) && !hasNamespace(node);});
|
|||
|
|
|||
|
var specifiers = restWithoutComments.
|
|||
|
map(function (node) {
|
|||
|
var tokens = sourceCode.getTokens(node);
|
|||
|
var openBrace = tokens.find(function (token) {return isPunctuator(token, '{');});
|
|||
|
var closeBrace = tokens.find(function (token) {return isPunctuator(token, '}');});
|
|||
|
|
|||
|
if (openBrace == null || closeBrace == null) {
|
|||
|
return undefined;
|
|||
|
}
|
|||
|
|
|||
|
return {
|
|||
|
importNode: node,
|
|||
|
identifiers: sourceCode.text.slice(openBrace.range[1], closeBrace.range[0]).split(','), // Split the text into separate identifiers (retaining any whitespace before or after)
|
|||
|
isEmpty: !hasSpecifiers(node) };
|
|||
|
|
|||
|
}).
|
|||
|
filter(Boolean);
|
|||
|
|
|||
|
var unnecessaryImports = restWithoutComments.filter(function (node) {return !hasSpecifiers(node) &&
|
|||
|
!hasNamespace(node) &&
|
|||
|
!specifiers.some(function (specifier) {return specifier.importNode === node;});});
|
|||
|
|
|||
|
|
|||
|
var shouldAddDefault = getDefaultImportName(first) == null && defaultImportNames.size === 1;
|
|||
|
var shouldAddSpecifiers = specifiers.length > 0;
|
|||
|
var shouldRemoveUnnecessary = unnecessaryImports.length > 0;
|
|||
|
var preferInline = context.options[0] && context.options[0]['prefer-inline'];
|
|||
|
|
|||
|
if (!(shouldAddDefault || shouldAddSpecifiers || shouldRemoveUnnecessary)) {
|
|||
|
return undefined;
|
|||
|
}
|
|||
|
|
|||
|
return function (fixer) {
|
|||
|
var tokens = sourceCode.getTokens(first);
|
|||
|
var openBrace = tokens.find(function (token) {return isPunctuator(token, '{');});
|
|||
|
var closeBrace = tokens.find(function (token) {return isPunctuator(token, '}');});
|
|||
|
var firstToken = sourceCode.getFirstToken(first);var _defaultImportNames = _slicedToArray(
|
|||
|
defaultImportNames, 1),defaultImportName = _defaultImportNames[0];
|
|||
|
|
|||
|
var firstHasTrailingComma = closeBrace != null && isPunctuator(sourceCode.getTokenBefore(closeBrace), ',');
|
|||
|
var firstIsEmpty = !hasSpecifiers(first);
|
|||
|
var firstExistingIdentifiers = firstIsEmpty ?
|
|||
|
new Set() :
|
|||
|
new Set(sourceCode.text.slice(openBrace.range[1], closeBrace.range[0]).
|
|||
|
split(',').
|
|||
|
map(function (x) {return x.trim();}));var _specifiers$reduce =
|
|||
|
|
|||
|
|
|||
|
specifiers.reduce(
|
|||
|
function (_ref, specifier) {var _ref2 = _slicedToArray(_ref, 3),result = _ref2[0],needsComma = _ref2[1],existingIdentifiers = _ref2[2];
|
|||
|
var isTypeSpecifier = specifier.importNode.importKind === 'type';
|
|||
|
|
|||
|
// a user might set prefer-inline but not have a supporting TypeScript version. Flow does not support inline types so this should fail in that case as well.
|
|||
|
if (preferInline && (!typescriptPkg || !_semver2['default'].satisfies(typescriptPkg.version, '>= 4.5'))) {
|
|||
|
throw new Error('Your version of TypeScript does not support inline type imports.');
|
|||
|
}
|
|||
|
|
|||
|
// Add *only* the new identifiers that don't already exist, and track any new identifiers so we don't add them again in the next loop
|
|||
|
var _specifier$identifier = specifier.identifiers.reduce(function (_ref3, cur) {var _ref4 = _slicedToArray(_ref3, 2),text = _ref4[0],set = _ref4[1];
|
|||
|
var trimmed = cur.trim(); // Trim whitespace before/after to compare to our set of existing identifiers
|
|||
|
var curWithType = trimmed.length > 0 && preferInline && isTypeSpecifier ? 'type ' + String(cur) : cur;
|
|||
|
if (existingIdentifiers.has(trimmed)) {
|
|||
|
return [text, set];
|
|||
|
}
|
|||
|
return [text.length > 0 ? String(text) + ',' + String(curWithType) : curWithType, set.add(trimmed)];
|
|||
|
}, ['', existingIdentifiers]),_specifier$identifier2 = _slicedToArray(_specifier$identifier, 2),specifierText = _specifier$identifier2[0],updatedExistingIdentifiers = _specifier$identifier2[1];
|
|||
|
|
|||
|
return [
|
|||
|
needsComma && !specifier.isEmpty && specifierText.length > 0 ? String(
|
|||
|
result) + ',' + String(specifierText) : '' + String(
|
|||
|
result) + String(specifierText),
|
|||
|
specifier.isEmpty ? needsComma : true,
|
|||
|
updatedExistingIdentifiers];
|
|||
|
|
|||
|
},
|
|||
|
['', !firstHasTrailingComma && !firstIsEmpty, firstExistingIdentifiers]),_specifiers$reduce2 = _slicedToArray(_specifiers$reduce, 1),specifiersText = _specifiers$reduce2[0];
|
|||
|
|
|||
|
|
|||
|
var fixes = [];
|
|||
|
|
|||
|
if (shouldAddSpecifiers && preferInline && first.importKind === 'type') {
|
|||
|
// `import type {a} from './foo'` → `import {type a} from './foo'`
|
|||
|
var typeIdentifierToken = tokens.find(function (token) {return token.type === 'Identifier' && token.value === 'type';});
|
|||
|
fixes.push(fixer.removeRange([typeIdentifierToken.range[0], typeIdentifierToken.range[1] + 1]));
|
|||
|
|
|||
|
tokens.
|
|||
|
filter(function (token) {return firstExistingIdentifiers.has(token.value);}).
|
|||
|
forEach(function (identifier) {
|
|||
|
fixes.push(fixer.replaceTextRange([identifier.range[0], identifier.range[1]], 'type ' + String(identifier.value)));
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
if (shouldAddDefault && openBrace == null && shouldAddSpecifiers) {
|
|||
|
// `import './foo'` → `import def, {...} from './foo'`
|
|||
|
fixes.push(
|
|||
|
fixer.insertTextAfter(firstToken, ' ' + String(defaultImportName) + ', {' + String(specifiersText) + '} from'));
|
|||
|
|
|||
|
} else if (shouldAddDefault && openBrace == null && !shouldAddSpecifiers) {
|
|||
|
// `import './foo'` → `import def from './foo'`
|
|||
|
fixes.push(fixer.insertTextAfter(firstToken, ' ' + String(defaultImportName) + ' from'));
|
|||
|
} else if (shouldAddDefault && openBrace != null && closeBrace != null) {
|
|||
|
// `import {...} from './foo'` → `import def, {...} from './foo'`
|
|||
|
fixes.push(fixer.insertTextAfter(firstToken, ' ' + String(defaultImportName) + ','));
|
|||
|
if (shouldAddSpecifiers) {
|
|||
|
// `import def, {...} from './foo'` → `import def, {..., ...} from './foo'`
|
|||
|
fixes.push(fixer.insertTextBefore(closeBrace, specifiersText));
|
|||
|
}
|
|||
|
} else if (!shouldAddDefault && openBrace == null && shouldAddSpecifiers) {
|
|||
|
if (first.specifiers.length === 0) {
|
|||
|
// `import './foo'` → `import {...} from './foo'`
|
|||
|
fixes.push(fixer.insertTextAfter(firstToken, ' {' + String(specifiersText) + '} from'));
|
|||
|
} else {
|
|||
|
// `import def from './foo'` → `import def, {...} from './foo'`
|
|||
|
fixes.push(fixer.insertTextAfter(first.specifiers[0], ', {' + String(specifiersText) + '}'));
|
|||
|
}
|
|||
|
} else if (!shouldAddDefault && openBrace != null && closeBrace != null) {
|
|||
|
// `import {...} './foo'` → `import {..., ...} from './foo'`
|
|||
|
fixes.push(fixer.insertTextBefore(closeBrace, specifiersText));
|
|||
|
}
|
|||
|
|
|||
|
// Remove imports whose specifiers have been moved into the first import.
|
|||
|
var _iteratorNormalCompletion = true;var _didIteratorError = false;var _iteratorError = undefined;try {for (var _iterator = specifiers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {var specifier = _step.value;
|
|||
|
var importNode = specifier.importNode;
|
|||
|
fixes.push(fixer.remove(importNode));
|
|||
|
|
|||
|
var charAfterImportRange = [importNode.range[1], importNode.range[1] + 1];
|
|||
|
var charAfterImport = sourceCode.text.substring(charAfterImportRange[0], charAfterImportRange[1]);
|
|||
|
if (charAfterImport === '\n') {
|
|||
|
fixes.push(fixer.removeRange(charAfterImportRange));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Remove imports whose default import has been moved to the first import,
|
|||
|
// and side-effect-only imports that are unnecessary due to the first
|
|||
|
// import.
|
|||
|
} catch (err) {_didIteratorError = true;_iteratorError = err;} finally {try {if (!_iteratorNormalCompletion && _iterator['return']) {_iterator['return']();}} finally {if (_didIteratorError) {throw _iteratorError;}}}var _iteratorNormalCompletion2 = true;var _didIteratorError2 = false;var _iteratorError2 = undefined;try {for (var _iterator2 = unnecessaryImports[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {var node = _step2.value;
|
|||
|
fixes.push(fixer.remove(node));
|
|||
|
|
|||
|
var charAfterImportRange = [node.range[1], node.range[1] + 1];
|
|||
|
var charAfterImport = sourceCode.text.substring(charAfterImportRange[0], charAfterImportRange[1]);
|
|||
|
if (charAfterImport === '\n') {
|
|||
|
fixes.push(fixer.removeRange(charAfterImportRange));
|
|||
|
}
|
|||
|
}} catch (err) {_didIteratorError2 = true;_iteratorError2 = err;} finally {try {if (!_iteratorNormalCompletion2 && _iterator2['return']) {_iterator2['return']();}} finally {if (_didIteratorError2) {throw _iteratorError2;}}}
|
|||
|
|
|||
|
return fixes;
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
function checkImports(imported, context) {var _iteratorNormalCompletion3 = true;var _didIteratorError3 = false;var _iteratorError3 = undefined;try {
|
|||
|
for (var _iterator3 = imported.entries()[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {var _ref5 = _step3.value;var _ref6 = _slicedToArray(_ref5, 2);var _module = _ref6[0];var nodes = _ref6[1];
|
|||
|
if (nodes.length > 1) {
|
|||
|
var message = '\'' + String(_module) + '\' imported multiple times.';var _nodes = _toArray(
|
|||
|
nodes),first = _nodes[0],rest = _nodes.slice(1);
|
|||
|
var sourceCode = context.getSourceCode();
|
|||
|
var fix = getFix(first, rest, sourceCode, context);
|
|||
|
|
|||
|
context.report({
|
|||
|
node: first.source,
|
|||
|
message: message,
|
|||
|
fix: fix // Attach the autofix (if any) to the first import.
|
|||
|
});var _iteratorNormalCompletion4 = true;var _didIteratorError4 = false;var _iteratorError4 = undefined;try {
|
|||
|
|
|||
|
for (var _iterator4 = rest[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {var node = _step4.value;
|
|||
|
context.report({
|
|||
|
node: node.source,
|
|||
|
message: message });
|
|||
|
|
|||
|
}} catch (err) {_didIteratorError4 = true;_iteratorError4 = err;} finally {try {if (!_iteratorNormalCompletion4 && _iterator4['return']) {_iterator4['return']();}} finally {if (_didIteratorError4) {throw _iteratorError4;}}}
|
|||
|
}
|
|||
|
}} catch (err) {_didIteratorError3 = true;_iteratorError3 = err;} finally {try {if (!_iteratorNormalCompletion3 && _iterator3['return']) {_iterator3['return']();}} finally {if (_didIteratorError3) {throw _iteratorError3;}}}
|
|||
|
}
|
|||
|
|
|||
|
module.exports = {
|
|||
|
meta: {
|
|||
|
type: 'problem',
|
|||
|
docs: {
|
|||
|
category: 'Style guide',
|
|||
|
description: 'Forbid repeated import of the same module in multiple places.',
|
|||
|
url: (0, _docsUrl2['default'])('no-duplicates') },
|
|||
|
|
|||
|
fixable: 'code',
|
|||
|
schema: [
|
|||
|
{
|
|||
|
type: 'object',
|
|||
|
properties: {
|
|||
|
considerQueryString: {
|
|||
|
type: 'boolean' },
|
|||
|
|
|||
|
'prefer-inline': {
|
|||
|
type: 'boolean' } },
|
|||
|
|
|||
|
|
|||
|
additionalProperties: false }] },
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
create: function () {function create(context) {
|
|||
|
// Prepare the resolver from options.
|
|||
|
var considerQueryStringOption = context.options[0] &&
|
|||
|
context.options[0].considerQueryString;
|
|||
|
var defaultResolver = function () {function defaultResolver(sourcePath) {return (0, _resolve2['default'])(sourcePath, context) || sourcePath;}return defaultResolver;}();
|
|||
|
var resolver = considerQueryStringOption ? function (sourcePath) {
|
|||
|
var parts = sourcePath.match(/^([^?]*)\?(.*)$/);
|
|||
|
if (!parts) {
|
|||
|
return defaultResolver(sourcePath);
|
|||
|
}
|
|||
|
return String(defaultResolver(parts[1])) + '?' + String(parts[2]);
|
|||
|
} : defaultResolver;
|
|||
|
|
|||
|
var moduleMaps = new Map();
|
|||
|
|
|||
|
function getImportMap(n) {
|
|||
|
if (!moduleMaps.has(n.parent)) {
|
|||
|
moduleMaps.set(n.parent, {
|
|||
|
imported: new Map(),
|
|||
|
nsImported: new Map(),
|
|||
|
defaultTypesImported: new Map(),
|
|||
|
namedTypesImported: new Map() });
|
|||
|
|
|||
|
}
|
|||
|
var map = moduleMaps.get(n.parent);
|
|||
|
var preferInline = context.options[0] && context.options[0]['prefer-inline'];
|
|||
|
if (!preferInline && n.importKind === 'type') {
|
|||
|
return n.specifiers.length > 0 && n.specifiers[0].type === 'ImportDefaultSpecifier' ? map.defaultTypesImported : map.namedTypesImported;
|
|||
|
}
|
|||
|
if (!preferInline && n.specifiers.some(function (spec) {return spec.importKind === 'type';})) {
|
|||
|
return map.namedTypesImported;
|
|||
|
}
|
|||
|
|
|||
|
return hasNamespace(n) ? map.nsImported : map.imported;
|
|||
|
}
|
|||
|
|
|||
|
return {
|
|||
|
ImportDeclaration: function () {function ImportDeclaration(n) {
|
|||
|
// resolved path will cover aliased duplicates
|
|||
|
var resolvedPath = resolver(n.source.value);
|
|||
|
var importMap = getImportMap(n);
|
|||
|
|
|||
|
if (importMap.has(resolvedPath)) {
|
|||
|
importMap.get(resolvedPath).push(n);
|
|||
|
} else {
|
|||
|
importMap.set(resolvedPath, [n]);
|
|||
|
}
|
|||
|
}return ImportDeclaration;}(),
|
|||
|
|
|||
|
'Program:exit': function () {function ProgramExit() {var _iteratorNormalCompletion5 = true;var _didIteratorError5 = false;var _iteratorError5 = undefined;try {
|
|||
|
for (var _iterator5 = moduleMaps.values()[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {var map = _step5.value;
|
|||
|
checkImports(map.imported, context);
|
|||
|
checkImports(map.nsImported, context);
|
|||
|
checkImports(map.defaultTypesImported, context);
|
|||
|
checkImports(map.namedTypesImported, context);
|
|||
|
}} catch (err) {_didIteratorError5 = true;_iteratorError5 = err;} finally {try {if (!_iteratorNormalCompletion5 && _iterator5['return']) {_iterator5['return']();}} finally {if (_didIteratorError5) {throw _iteratorError5;}}}
|
|||
|
}return ProgramExit;}() };
|
|||
|
|
|||
|
}return create;}() };
|
|||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydWxlcy9uby1kdXBsaWNhdGVzLmpzIl0sIm5hbWVzIjpbInR5cGVzY3JpcHRQa2ciLCJyZXF1aXJlIiwiZSIsImlzUHVuY3R1YXRvciIsIm5vZGUiLCJ2YWx1ZSIsInR5cGUiLCJnZXREZWZhdWx0SW1wb3J0TmFtZSIsImRlZmF1bHRTcGVjaWZpZXIiLCJzcGVjaWZpZXJzIiwiZmluZCIsInNwZWNpZmllciIsImxvY2FsIiwibmFtZSIsInVuZGVmaW5lZCIsImhhc05hbWVzcGFjZSIsImZpbHRlciIsImxlbmd0aCIsImhhc1NwZWNpZmllcnMiLCJoYXNDb21tZW50QmVmb3JlIiwic291cmNlQ29kZSIsImdldENvbW1lbnRzQmVmb3JlIiwic29tZSIsImNvbW1lbnQiLCJsb2MiLCJlbmQiLCJsaW5lIiwic3RhcnQiLCJoYXNDb21tZW50QWZ0ZXIiLCJnZXRDb21tZW50c0FmdGVyIiwiaGFzQ29tbWVudEluc2lkZU5vblNwZWNpZmllcnMiLCJ0b2tlbnMiLCJnZXRUb2tlbnMiLCJvcGVuQnJhY2VJbmRleCIsImZpbmRJbmRleCIsInRva2VuIiwiY2xvc2VCcmFjZUluZGV4Iiwic29tZVRva2VucyIsInNsaWNlIiwiY29uY2F0IiwiaGFzUHJvYmxlbWF0aWNDb21tZW50cyIsImdldEZpeCIsImZpcnN0IiwicmVzdCIsImNvbnRleHQiLCJkZWZhdWx0SW1wb3J0TmFtZXMiLCJTZXQiLCJ4Iiwic2l6ZSIsInJlc3RXaXRob3V0Q29tbWVudHMiLCJtYXAiLCJvcGVuQnJhY2UiLCJjbG9zZUJyYWNlIiwiaW1wb3J0Tm9kZSIsImlkZW50aWZpZXJzIiwidGV4dCIsInJhbmdlIiwic3BsaXQiLCJpc0VtcHR5IiwiQm9vbGVhbiIsInVubmVjZXNzYXJ5SW1wb3J0cyIsInNob3VsZEFkZERlZmF1bHQiLCJzaG91bGRBZGRTcGVjaWZpZXJzIiwic2hvdWxkUmVtb3ZlVW5uZWNlc3NhcnkiLCJwcmVmZXJJbmxpbmUiLCJvcHRpb25zIiwiZml4ZXIiLCJmaXJzdFRva2VuIiwiZ2V0Rmlyc3RUb2tlbiIsImRlZmF1bHRJbXBvcnROYW1lIiwiZmlyc3RIYXNUcmFpbGluZ0NvbW1hIiwiZ2V0VG9rZW5CZWZvcmUiLCJmaXJzdElzRW1wdHkiLCJmaXJzdEV4aXN0aW5nSWRlbnRpZmllcnMiLCJ0cmltIiwicmVkdWNlIiwicmVzdWx0IiwibmVlZHNDb21tYSIsImV4aXN0aW5nSWRlbnRpZmllcnMiLCJpc1R5cGVTcGVjaWZpZXIiLCJpbXBvcnRLaW5kIiwic2VtdmVyIiwic2F0aXNmaWVzIiwidmVyc2lvbiIsIkVycm9yIiwiY3VyIiwic2V0IiwidHJpbW1lZCIsImN1cldpdGhUeXBlIiwiaGFzIiwiYWRkIiwic3BlY2lmaWVyVGV4dCIsInVwZGF0ZWRFeGlzdGluZ0lkZW50aWZpZXJzIiwic3BlY2lmaWVyc1RleHQiLCJmaXhlcyIsInR5cGVJZGVudGlmaWVyVG9rZW4iLCJwdXNoIiwicmVtb3ZlUmFuZ2UiLCJmb3JFYWNoIiwiaWRlbnRpZmllciIsInJlcGxhY2VUZXh0UmFuZ2UiLCJpbnNlcnRUZXh0QWZ0ZXIiLCJpbnNlcnRUZXh0QmVmb3JlIiwicmVtb3ZlIiwiY2hhckFmdGVySW1wb3J0UmFuZ2UiLCJjaGFyQWZ0ZXJJbXBvcnQiLCJzdWJzdHJpbmciLCJjaGVja0ltcG9ydHMiLCJpbXBvcnRlZCIsImVudHJpZXMiLCJtb2R1bGUiLCJub2RlcyIsIm1lc3NhZ2UiLCJnZXRTb3VyY2VDb2RlIiwiZml4IiwicmVwb3J0Iiwic291cmNlIiwiZXhwb3J0cyIsIm1ldGEiLCJkb2NzIiwiY2F0ZWdvcnkiLCJkZXNjcmlwdGlvbiIsInVybCIsImZpeGFibGUiLCJzY2hlbWEiLCJwcm9wZXJ0aWVzIiwiY29uc2lkZXJRdWVyeVN0cmluZyIsImFkZGl0aW9uYWxQcm9wZXJ0aWVzIiwiY3JlYXRlIiwiY29uc2lkZXJRdWVyeVN0cmluZ09wdGlvbiIsImRlZmF1bHRSZXNvbHZlciIsInNvdXJjZVBhdGgiLCJyZXNvbHZlciIsInBhcnRzIiwibWF0Y2giLCJtb2R1bGVNYXBzIiwiTWFwIiwiZ2V0SW1wb3J0TWFwIiwibiIsInBhcmVudCIsIm5zSW1wb3J0ZWQiLCJkZWZhdWx0VHlwZXNJbXBvcnRlZCIsIm5hbWVkVHlwZXNJbXBvcnRlZCIsImdldCIsInNwZWMiLCJJbXBvcnREZWNsYXJhdGlvbiIsInJlc29sdmVkUGF0aCIsImltcG9ydE1hcCIsInZhbHVlcyJdLCJtYXBwaW5ncyI6InFvQkFBQSxzRDtBQUNBLGdDO0FBQ0EseUQ7O0FBRUEscUM7O0FBRUEsSUFBSUEsc0JBQUo7QUFDQSxJQUFJO0FBQ0ZBLGtCQUFnQkMsUUFBUSx5QkFBUixDQUFoQixDQURFLENBQ2tEO0FBQ3JELENBRkQsQ0FFRSxPQUFPQyxDQUFQLEVBQVUsQ0FBRSxJQUFNOztBQUVwQixTQUFTQyxZQUFULENBQXNCQyxJQUF0QixFQUE0QkMsS0FBNUIsRUFBbUM7QUFDakMsU0FBT0QsS0FBS0UsSUFBTCxLQUFjLFlBQWQsSUFBOEJGLEtBQUtDLEtBQUwsS0FBZUEsS0FBcEQ7QUFDRDs7QUFFRDtBQUNBLFNBQVNFLG9CQUFULENBQThCSCxJQUE5QixFQUFvQztBQUNsQyxNQUFNSSxtQkFBbUJKLEtBQUtLLFVBQUw7QUFDdEJDLE1BRHNCLENBQ2pCLFVBQUNDLFNBQUQsVUFBZUEsVUFBVUwsSUFBVixLQUFtQix3QkFBbEMsRUFEaUIsQ0FBekI7QUFFQSxTQUFPRSxvQkFBb0IsSUFBcEIsR0FBMkJBLGlCQUFpQkksS0FBakIsQ0FBdUJDLElBQWxELEdBQXlEQyxTQUFoRTtBQUNEOztBQUVEO0FBQ0EsU0FBU0MsWUFBVCxDQUFzQlgsSUFBdEIsRUFBNEI7QUFDMUIsTUFBTUssYUFBYUwsS0FBS0ssVUFBTDtBQUNoQk8sUUFEZ0IsQ0FDVCxVQUFDTCxTQUFELFVBQWVBLFVBQVVMLElBQVYsS0FBbUIsMEJBQWxDLEVBRFMsQ0FBbkI7QUFFQSxTQUFPRyxXQUFXUSxNQUFYLEdBQW9CLENBQTNCO0FBQ0Q7O0FBRUQ7QUFDQSxTQUFTQyxhQUFULENBQXVCZCxJQUF2QixFQUE2QjtBQUMzQixNQUFNSyxhQUFhTCxLQUFLSyxVQUFMO0FBQ2hCTyxRQURnQixDQUNULFVBQUNMLFNBQUQsVUFBZUEsVUFBVUwsSUFBVixLQUFtQixpQkFBbEMsRUFEUyxDQUFuQjtBQUVBLFNBQU9HLFdBQVdRLE1BQVgsR0FBb0IsQ0FBM0I7QUFDRDs7QUFFRDtBQUNBO0FBQ0EsU0FBU0UsZ0JBQVQsQ0FBMEJmLElBQTFCLEVBQWdDZ0IsVUFBaEMsRUFBNEM7QUFDMUMsU0FBT0EsV0FBV0MsaUJBQVgsQ0FBNkJqQixJQUE3QjtBQUNKa0IsTUFESSxDQUNDLFVBQUNDLE9BQUQsVUFBYUEsUUFBUUMsR0FBUixDQUFZQyxHQUFaLENBQWdCQyxJQUFoQixJQUF3QnRCLEtBQUtvQixHQUFMLENBQVNHLEtBQVQsQ0F
|