245 lines
30 KiB
JavaScript
245 lines
30 KiB
JavaScript
|
'use strict';var _path = require('path');var _path2 = _interopRequireDefault(_path);
|
||
|
|
||
|
var _resolve = require('eslint-module-utils/resolve');var _resolve2 = _interopRequireDefault(_resolve);
|
||
|
var _moduleVisitor = require('eslint-module-utils/moduleVisitor');var _moduleVisitor2 = _interopRequireDefault(_moduleVisitor);
|
||
|
var _isGlob = require('is-glob');var _isGlob2 = _interopRequireDefault(_isGlob);
|
||
|
var _minimatch = require('minimatch');
|
||
|
var _docsUrl = require('../docsUrl');var _docsUrl2 = _interopRequireDefault(_docsUrl);
|
||
|
var _importType = require('../core/importType');var _importType2 = _interopRequireDefault(_importType);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { 'default': obj };}
|
||
|
|
||
|
var containsPath = function containsPath(filepath, target) {
|
||
|
var relative = _path2['default'].relative(target, filepath);
|
||
|
return relative === '' || !relative.startsWith('..');
|
||
|
};
|
||
|
|
||
|
function isMatchingTargetPath(filename, targetPath) {
|
||
|
if ((0, _isGlob2['default'])(targetPath)) {
|
||
|
var mm = new _minimatch.Minimatch(targetPath);
|
||
|
return mm.match(filename);
|
||
|
}
|
||
|
|
||
|
return containsPath(filename, targetPath);
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
meta: {
|
||
|
type: 'problem',
|
||
|
docs: {
|
||
|
category: 'Static analysis',
|
||
|
description: 'Enforce which files can be imported in a given folder.',
|
||
|
url: (0, _docsUrl2['default'])('no-restricted-paths') },
|
||
|
|
||
|
|
||
|
schema: [
|
||
|
{
|
||
|
type: 'object',
|
||
|
properties: {
|
||
|
zones: {
|
||
|
type: 'array',
|
||
|
minItems: 1,
|
||
|
items: {
|
||
|
type: 'object',
|
||
|
properties: {
|
||
|
target: {
|
||
|
anyOf: [
|
||
|
{ type: 'string' },
|
||
|
{
|
||
|
type: 'array',
|
||
|
items: { type: 'string' },
|
||
|
uniqueItems: true,
|
||
|
minLength: 1 }] },
|
||
|
|
||
|
|
||
|
|
||
|
from: {
|
||
|
anyOf: [
|
||
|
{ type: 'string' },
|
||
|
{
|
||
|
type: 'array',
|
||
|
items: { type: 'string' },
|
||
|
uniqueItems: true,
|
||
|
minLength: 1 }] },
|
||
|
|
||
|
|
||
|
|
||
|
except: {
|
||
|
type: 'array',
|
||
|
items: {
|
||
|
type: 'string' },
|
||
|
|
||
|
uniqueItems: true },
|
||
|
|
||
|
message: { type: 'string' } },
|
||
|
|
||
|
additionalProperties: false } },
|
||
|
|
||
|
|
||
|
basePath: { type: 'string' } },
|
||
|
|
||
|
additionalProperties: false }] },
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
create: function () {function noRestrictedPaths(context) {
|
||
|
var options = context.options[0] || {};
|
||
|
var restrictedPaths = options.zones || [];
|
||
|
var basePath = options.basePath || process.cwd();
|
||
|
var currentFilename = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
|
||
|
var matchingZones = restrictedPaths.filter(
|
||
|
function (zone) {return [].concat(zone.target).
|
||
|
map(function (target) {return _path2['default'].resolve(basePath, target);}).
|
||
|
some(function (targetPath) {return isMatchingTargetPath(currentFilename, targetPath);});});
|
||
|
|
||
|
|
||
|
function isValidExceptionPath(absoluteFromPath, absoluteExceptionPath) {
|
||
|
var relativeExceptionPath = _path2['default'].relative(absoluteFromPath, absoluteExceptionPath);
|
||
|
|
||
|
return (0, _importType2['default'])(relativeExceptionPath, context) !== 'parent';
|
||
|
}
|
||
|
|
||
|
function areBothGlobPatternAndAbsolutePath(areGlobPatterns) {
|
||
|
return areGlobPatterns.some(function (isGlob) {return isGlob;}) && areGlobPatterns.some(function (isGlob) {return !isGlob;});
|
||
|
}
|
||
|
|
||
|
function reportInvalidExceptionPath(node) {
|
||
|
context.report({
|
||
|
node: node,
|
||
|
message: 'Restricted path exceptions must be descendants of the configured `from` path for that zone.' });
|
||
|
|
||
|
}
|
||
|
|
||
|
function reportInvalidExceptionMixedGlobAndNonGlob(node) {
|
||
|
context.report({
|
||
|
node: node,
|
||
|
message: 'Restricted path `from` must contain either only glob patterns or none' });
|
||
|
|
||
|
}
|
||
|
|
||
|
function reportInvalidExceptionGlob(node) {
|
||
|
context.report({
|
||
|
node: node,
|
||
|
message: 'Restricted path exceptions must be glob patterns when `from` contains glob patterns' });
|
||
|
|
||
|
}
|
||
|
|
||
|
function computeMixedGlobAndAbsolutePathValidator() {
|
||
|
return {
|
||
|
isPathRestricted: function () {function isPathRestricted() {return true;}return isPathRestricted;}(),
|
||
|
hasValidExceptions: false,
|
||
|
reportInvalidException: reportInvalidExceptionMixedGlobAndNonGlob };
|
||
|
|
||
|
}
|
||
|
|
||
|
function computeGlobPatternPathValidator(absoluteFrom, zoneExcept) {
|
||
|
var isPathException = void 0;
|
||
|
|
||
|
var mm = new _minimatch.Minimatch(absoluteFrom);
|
||
|
var isPathRestricted = function () {function isPathRestricted(absoluteImportPath) {return mm.match(absoluteImportPath);}return isPathRestricted;}();
|
||
|
var hasValidExceptions = zoneExcept.every(_isGlob2['default']);
|
||
|
|
||
|
if (hasValidExceptions) {
|
||
|
var exceptionsMm = zoneExcept.map(function (except) {return new _minimatch.Minimatch(except);});
|
||
|
isPathException = function () {function isPathException(absoluteImportPath) {return exceptionsMm.some(function (mm) {return mm.match(absoluteImportPath);});}return isPathException;}();
|
||
|
}
|
||
|
|
||
|
var reportInvalidException = reportInvalidExceptionGlob;
|
||
|
|
||
|
return {
|
||
|
isPathRestricted: isPathRestricted,
|
||
|
hasValidExceptions: hasValidExceptions,
|
||
|
isPathException: isPathException,
|
||
|
reportInvalidException: reportInvalidException };
|
||
|
|
||
|
}
|
||
|
|
||
|
function computeAbsolutePathValidator(absoluteFrom, zoneExcept) {
|
||
|
var isPathException = void 0;
|
||
|
|
||
|
var isPathRestricted = function () {function isPathRestricted(absoluteImportPath) {return containsPath(absoluteImportPath, absoluteFrom);}return isPathRestricted;}();
|
||
|
|
||
|
var absoluteExceptionPaths = zoneExcept.
|
||
|
map(function (exceptionPath) {return _path2['default'].resolve(absoluteFrom, exceptionPath);});
|
||
|
var hasValidExceptions = absoluteExceptionPaths.
|
||
|
every(function (absoluteExceptionPath) {return isValidExceptionPath(absoluteFrom, absoluteExceptionPath);});
|
||
|
|
||
|
if (hasValidExceptions) {
|
||
|
isPathException = function () {function isPathException(absoluteImportPath) {return absoluteExceptionPaths.some(
|
||
|
function (absoluteExceptionPath) {return containsPath(absoluteImportPath, absoluteExceptionPath);});}return isPathException;}();
|
||
|
|
||
|
}
|
||
|
|
||
|
var reportInvalidException = reportInvalidExceptionPath;
|
||
|
|
||
|
return {
|
||
|
isPathRestricted: isPathRestricted,
|
||
|
hasValidExceptions: hasValidExceptions,
|
||
|
isPathException: isPathException,
|
||
|
reportInvalidException: reportInvalidException };
|
||
|
|
||
|
}
|
||
|
|
||
|
function reportInvalidExceptions(validators, node) {
|
||
|
validators.forEach(function (validator) {return validator.reportInvalidException(node);});
|
||
|
}
|
||
|
|
||
|
function reportImportsInRestrictedZone(validators, node, importPath, customMessage) {
|
||
|
validators.forEach(function () {
|
||
|
context.report({
|
||
|
node: node,
|
||
|
message: 'Unexpected path "{{importPath}}" imported in restricted zone.' + (customMessage ? ' ' + String(customMessage) : ''),
|
||
|
data: { importPath: importPath } });
|
||
|
|
||
|
});
|
||
|
}
|
||
|
|
||
|
var makePathValidators = function () {function makePathValidators(zoneFrom) {var zoneExcept = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
||
|
var allZoneFrom = [].concat(zoneFrom);
|
||
|
var areGlobPatterns = allZoneFrom.map(_isGlob2['default']);
|
||
|
|
||
|
if (areBothGlobPatternAndAbsolutePath(areGlobPatterns)) {
|
||
|
return [computeMixedGlobAndAbsolutePathValidator()];
|
||
|
}
|
||
|
|
||
|
var isGlobPattern = areGlobPatterns.every(function (isGlob) {return isGlob;});
|
||
|
|
||
|
return allZoneFrom.map(function (singleZoneFrom) {
|
||
|
var absoluteFrom = _path2['default'].resolve(basePath, singleZoneFrom);
|
||
|
|
||
|
if (isGlobPattern) {
|
||
|
return computeGlobPatternPathValidator(absoluteFrom, zoneExcept);
|
||
|
}
|
||
|
return computeAbsolutePathValidator(absoluteFrom, zoneExcept);
|
||
|
});
|
||
|
}return makePathValidators;}();
|
||
|
|
||
|
var validators = [];
|
||
|
|
||
|
function checkForRestrictedImportPath(importPath, node) {
|
||
|
var absoluteImportPath = (0, _resolve2['default'])(importPath, context);
|
||
|
|
||
|
if (!absoluteImportPath) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
matchingZones.forEach(function (zone, index) {
|
||
|
if (!validators[index]) {
|
||
|
validators[index] = makePathValidators(zone.from, zone.except);
|
||
|
}
|
||
|
|
||
|
var applicableValidatorsForImportPath = validators[index].filter(function (validator) {return validator.isPathRestricted(absoluteImportPath);});
|
||
|
|
||
|
var validatorsWithInvalidExceptions = applicableValidatorsForImportPath.filter(function (validator) {return !validator.hasValidExceptions;});
|
||
|
reportInvalidExceptions(validatorsWithInvalidExceptions, node);
|
||
|
|
||
|
var applicableValidatorsForImportPathExcludingExceptions = applicableValidatorsForImportPath.
|
||
|
filter(function (validator) {return validator.hasValidExceptions && !validator.isPathException(absoluteImportPath);});
|
||
|
reportImportsInRestrictedZone(applicableValidatorsForImportPathExcludingExceptions, node, importPath, zone.message);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return (0, _moduleVisitor2['default'])(function (source) {
|
||
|
checkForRestrictedImportPath(source.value, source);
|
||
|
}, { commonjs: true });
|
||
|
}return noRestrictedPaths;}() };
|
||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydWxlcy9uby1yZXN0cmljdGVkLXBhdGhzLmpzIl0sIm5hbWVzIjpbImNvbnRhaW5zUGF0aCIsImZpbGVwYXRoIiwidGFyZ2V0IiwicmVsYXRpdmUiLCJwYXRoIiwic3RhcnRzV2l0aCIsImlzTWF0Y2hpbmdUYXJnZXRQYXRoIiwiZmlsZW5hbWUiLCJ0YXJnZXRQYXRoIiwibW0iLCJNaW5pbWF0Y2giLCJtYXRjaCIsIm1vZHVsZSIsImV4cG9ydHMiLCJtZXRhIiwidHlwZSIsImRvY3MiLCJjYXRlZ29yeSIsImRlc2NyaXB0aW9uIiwidXJsIiwic2NoZW1hIiwicHJvcGVydGllcyIsInpvbmVzIiwibWluSXRlbXMiLCJpdGVtcyIsImFueU9mIiwidW5pcXVlSXRlbXMiLCJtaW5MZW5ndGgiLCJmcm9tIiwiZXhjZXB0IiwibWVzc2FnZSIsImFkZGl0aW9uYWxQcm9wZXJ0aWVzIiwiYmFzZVBhdGgiLCJjcmVhdGUiLCJub1Jlc3RyaWN0ZWRQYXRocyIsImNvbnRleHQiLCJvcHRpb25zIiwicmVzdHJpY3RlZFBhdGhzIiwicHJvY2VzcyIsImN3ZCIsImN1cnJlbnRGaWxlbmFtZSIsImdldFBoeXNpY2FsRmlsZW5hbWUiLCJnZXRGaWxlbmFtZSIsIm1hdGNoaW5nWm9uZXMiLCJmaWx0ZXIiLCJ6b25lIiwiY29uY2F0IiwibWFwIiwicmVzb2x2ZSIsInNvbWUiLCJpc1ZhbGlkRXhjZXB0aW9uUGF0aCIsImFic29sdXRlRnJvbVBhdGgiLCJhYnNvbHV0ZUV4Y2VwdGlvblBhdGgiLCJyZWxhdGl2ZUV4Y2VwdGlvblBhdGgiLCJhcmVCb3RoR2xvYlBhdHRlcm5BbmRBYnNvbHV0ZVBhdGgiLCJhcmVHbG9iUGF0dGVybnMiLCJpc0dsb2IiLCJyZXBvcnRJbnZhbGlkRXhjZXB0aW9uUGF0aCIsIm5vZGUiLCJyZXBvcnQiLCJyZXBvcnRJbnZhbGlkRXhjZXB0aW9uTWl4ZWRHbG9iQW5kTm9uR2xvYiIsInJlcG9ydEludmFsaWRFeGNlcHRpb25HbG9iIiwiY29tcHV0ZU1peGVkR2xvYkFuZEFic29sdXRlUGF0aFZhbGlkYXRvciIsImlzUGF0aFJlc3RyaWN0ZWQiLCJoYXNWYWxpZEV4Y2VwdGlvbnMiLCJyZXBvcnRJbnZhbGlkRXhjZXB0aW9uIiwiY29tcHV0ZUdsb2JQYXR0ZXJuUGF0aFZhbGlkYXRvciIsImFic29sdXRlRnJvbSIsInpvbmVFeGNlcHQiLCJpc1BhdGhFeGNlcHRpb24iLCJhYnNvbHV0ZUltcG9ydFBhdGgiLCJldmVyeSIsImV4Y2VwdGlvbnNNbSIsImNvbXB1dGVBYnNvbHV0ZVBhdGhWYWxpZGF0b3IiLCJhYnNvbHV0ZUV4Y2VwdGlvblBhdGhzIiwiZXhjZXB0aW9uUGF0aCIsInJlcG9ydEludmFsaWRFeGNlcHRpb25zIiwidmFsaWRhdG9ycyIsImZvckVhY2giLCJ2YWxpZGF0b3IiLCJyZXBvcnRJbXBvcnRzSW5SZXN0cmljdGVkWm9uZSIsImltcG9ydFBhdGgiLCJjdXN0b21NZXNzYWdlIiwiZGF0YSIsIm1ha2VQYXRoVmFsaWRhdG9ycyIsInpvbmVGcm9tIiwiYWxsWm9uZUZyb20iLCJpc0dsb2JQYXR0ZXJuIiwic2luZ2xlWm9uZUZyb20iLCJjaGVja0ZvclJlc3RyaWN0ZWRJbXBvcnRQYXRoIiwiaW5kZXgiLCJhcHBsaWNhYmxlVmFsaWRhdG9yc0ZvckltcG9ydFBhdGgiLCJ2YWxpZGF0b3JzV2l0aEludmFsaWRFeGNlcHRpb25zIiwiYXBwbGljYWJsZVZhbGlkYXRvcnNGb3JJbXBvcnRQYXRoRXhjbHVkaW5nRXhjZXB0aW9ucyIsInNvdXJjZSIsInZhbHVlIiwiY29tbW9uanMiXSwibWFwcGluZ3MiOiJhQUFBLDRCOztBQUVBLHNEO0FBQ0Esa0U7QUFDQSxpQztBQUNBO0FBQ0EscUM7QUFDQSxnRDs7QUFFQSxJQUFNQSxlQUFlLFNBQWZBLFlBQWUsQ0FBQ0MsUUFBRCxFQUFXQyxNQUFYLEVBQXNCO0FBQ3pDLE1BQU1DLFdBQVdDLGtCQUFLRCxRQUFMLENBQWNELE1BQWQsRUFBc0JELFFBQXRCLENBQWpCO0FBQ0EsU0FBT0UsYUFBYSxFQUFiLElBQW1CLENBQUNBLFNBQVNFLFVBQVQsQ0FBb0IsSUFBcEIsQ0FBM0I7QUFDRCxDQUhEOztBQUtBLFNBQVNDLG9CQUFULENBQThCQyxRQUE5QixFQUF3Q0MsVUFBeEMsRUFBb0Q7QUFDbEQsTUFBSSx5QkFBT0EsVUFBUCxDQUFKLEVBQXdCO0FBQ3RCLFFBQU1DLEtBQUssSUFBSUMsb0JBQUosQ0FBY0YsVUFBZCxDQUFYO0FBQ0EsV0FBT0MsR0FBR0UsS0FBSCxDQUFTSixRQUFULENBQVA7QUFDRDs7QUFFRCxTQUFPUCxhQUFhTyxRQUFiLEVBQXVCQyxVQUF2QixDQUFQO0FBQ0Q7O0FBRURJLE9BQU9DLE9BQVAsR0FBaUI7QUFDZkMsUUFBTTtBQUNKQyxVQUFNLFNBREY7QUFFSkMsVUFBTTtBQUNKQyxnQkFBVSxpQkFETjtBQUVKQyxtQkFBYSx3REFGVDtBQUdKQyxXQUFLLDBCQUFRLHFCQUFSLENBSEQsRUFGRjs7O0FBUUpDLFlBQVE7QUFDTjtBQUNFTCxZQUFNLFFBRFI7QUFFRU0sa0JBQVk7QUFDVkMsZUFBTztBQUNMUCxnQkFBTSxPQUREO0FBRUxRLG9CQUFVLENBRkw7QUFHTEMsaUJBQU87QUFDTFQsa0JBQU0sUUFERDtBQUVMTSx3QkFBWTtBQUNWbkIsc0JBQVE7QUFDTnVCLHVCQUFPO0FBQ0wsa0JBQUVWLE1BQU0sUUFBUixFQURLO0FBRUw7QUFDRUEsd0JBQU0sT0FEUjtBQUVFUyx5QkFBTyxFQUFFVCxNQUFNLFFBQVIsRUFGVDtBQUdFVywrQkFBYSxJQUhmO0FBSUVDLDZCQUFXLENBSmIsRUFGSyxDQURELEVBREU7Ozs7QUFZVkMsb0JBQU07QUFDSkgsdUJBQU87QUFDTCxrQkFBRVYsTUFBTSxRQUFSLEVBREs7QUFFTDtBQUNFQSx3QkFBTSxPQURSO0FBRUVTLHlCQUFPLEVBQUVULE1BQU0sUUFBUixFQUZUO0FBR0VXLCtCQUFhLElBSGY7QUFJRUMsNkJBQVcsQ0FKYixFQUZLLENBREgsRUFaSTs7OztBQXVCVkUsc0JBQVE7QUFDTmQsc0JBQU0sT0FEQTtBQUVOUyx1QkFBTztBQUNMVCx3QkFBTSxRQURELEVBRkQ7O0FBS05XLDZCQUFhLElBTFAsRUF2QkU7O0FBOEJWSSx1QkFBUyxFQUFFZixNQUFNLFFBQVIsRUE5QkMsRUFGUDs7QUFrQ0xnQixrQ0FBc0IsS0FsQ2pCLEVBSEYsRUFERzs7O0FBeUNWQyxrQkFBVSxFQUFFakIsTUFBTSxRQUFSLEVBekNBLEVBRmQ7O0FBNkNFZ0IsNEJBQXNCLEtBN0N4QixFQURNLENBUkosRUFEUzs7Ozs7QUE0RGZFLHVCQUFRLFNBQVNDLGlCQUFULENBQTJCQyxPQUEzQixFQUFvQztBQUMxQyxVQUFNQyxVQUFVRCxRQUFRQyxPQUFSLENBQWdCLENBQWhCLEtBQXNCLEVBQXRDO0FBQ0EsVUFBTUMsa0JBQWtCRCxRQUF
|