237 lines
8.5 KiB
Plaintext
237 lines
8.5 KiB
Plaintext
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const utils_1 = require("@typescript-eslint/utils");
|
|
const ignore_1 = __importDefault(require("ignore"));
|
|
const util_1 = require("../util");
|
|
const getESLintCoreRule_1 = require("../util/getESLintCoreRule");
|
|
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('no-restricted-imports');
|
|
// In some versions of eslint, the base rule has a completely incompatible schema
|
|
// This helper function is to safely try to get parts of the schema. If it's not
|
|
// possible, we'll fallback to less strict checks.
|
|
const tryAccess = (getter, fallback) => {
|
|
try {
|
|
return getter();
|
|
}
|
|
catch {
|
|
return fallback;
|
|
}
|
|
};
|
|
const baseSchema = baseRule.meta.schema;
|
|
const allowTypeImportsOptionSchema = {
|
|
allowTypeImports: {
|
|
type: 'boolean',
|
|
description: 'Disallow value imports, but allow type-only imports.',
|
|
},
|
|
};
|
|
const arrayOfStringsOrObjects = {
|
|
type: 'array',
|
|
items: {
|
|
anyOf: [
|
|
{ type: 'string' },
|
|
{
|
|
type: 'object',
|
|
additionalProperties: false,
|
|
properties: {
|
|
...tryAccess(() => baseSchema.anyOf[1].items[0].properties.paths.items.anyOf[1]
|
|
.properties, undefined),
|
|
...allowTypeImportsOptionSchema,
|
|
},
|
|
required: tryAccess(() => baseSchema.anyOf[1].items[0].properties.paths.items.anyOf[1]
|
|
.required, undefined),
|
|
},
|
|
],
|
|
},
|
|
uniqueItems: true,
|
|
};
|
|
const arrayOfStringsOrObjectPatterns = {
|
|
anyOf: [
|
|
{
|
|
type: 'array',
|
|
items: {
|
|
type: 'string',
|
|
},
|
|
uniqueItems: true,
|
|
},
|
|
{
|
|
type: 'array',
|
|
items: {
|
|
type: 'object',
|
|
additionalProperties: false,
|
|
properties: {
|
|
...tryAccess(() => baseSchema.anyOf[1].items[0].properties.patterns.anyOf[1].items
|
|
.properties, undefined),
|
|
...allowTypeImportsOptionSchema,
|
|
},
|
|
required: tryAccess(() => baseSchema.anyOf[1].items[0].properties.patterns.anyOf[1].items
|
|
.required, []),
|
|
},
|
|
uniqueItems: true,
|
|
},
|
|
],
|
|
};
|
|
const schema = {
|
|
anyOf: [
|
|
arrayOfStringsOrObjects,
|
|
{
|
|
type: 'array',
|
|
items: [
|
|
{
|
|
type: 'object',
|
|
properties: {
|
|
paths: arrayOfStringsOrObjects,
|
|
patterns: arrayOfStringsOrObjectPatterns,
|
|
},
|
|
additionalProperties: false,
|
|
},
|
|
],
|
|
additionalItems: false,
|
|
},
|
|
],
|
|
};
|
|
function isObjectOfPaths(obj) {
|
|
return Object.prototype.hasOwnProperty.call(obj, 'paths');
|
|
}
|
|
function isObjectOfPatterns(obj) {
|
|
return Object.prototype.hasOwnProperty.call(obj, 'patterns');
|
|
}
|
|
function isOptionsArrayOfStringOrObject(options) {
|
|
if (isObjectOfPaths(options[0])) {
|
|
return false;
|
|
}
|
|
if (isObjectOfPatterns(options[0])) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
function getRestrictedPaths(options) {
|
|
if (isOptionsArrayOfStringOrObject(options)) {
|
|
return options;
|
|
}
|
|
if (isObjectOfPaths(options[0])) {
|
|
return options[0].paths;
|
|
}
|
|
return [];
|
|
}
|
|
function getRestrictedPatterns(options) {
|
|
if (isObjectOfPatterns(options[0])) {
|
|
return options[0].patterns;
|
|
}
|
|
return [];
|
|
}
|
|
function shouldCreateRule(baseRules, options) {
|
|
if (Object.keys(baseRules).length === 0 || options.length === 0) {
|
|
return false;
|
|
}
|
|
if (!isOptionsArrayOfStringOrObject(options)) {
|
|
return !!(options[0].paths?.length || options[0].patterns?.length);
|
|
}
|
|
return true;
|
|
}
|
|
exports.default = (0, util_1.createRule)({
|
|
name: 'no-restricted-imports',
|
|
meta: {
|
|
type: 'suggestion',
|
|
docs: {
|
|
description: 'Disallow specified modules when loaded by `import`',
|
|
extendsBaseRule: true,
|
|
},
|
|
messages: baseRule.meta.messages,
|
|
fixable: baseRule.meta.fixable,
|
|
schema,
|
|
},
|
|
defaultOptions: [],
|
|
create(context) {
|
|
const rules = baseRule.create(context);
|
|
const { options } = context;
|
|
if (!shouldCreateRule(rules, options)) {
|
|
return {};
|
|
}
|
|
const restrictedPaths = getRestrictedPaths(options);
|
|
const allowedTypeImportPathNameSet = new Set();
|
|
for (const restrictedPath of restrictedPaths) {
|
|
if (typeof restrictedPath === 'object' &&
|
|
restrictedPath.allowTypeImports) {
|
|
allowedTypeImportPathNameSet.add(restrictedPath.name);
|
|
}
|
|
}
|
|
function isAllowedTypeImportPath(importSource) {
|
|
return allowedTypeImportPathNameSet.has(importSource);
|
|
}
|
|
const restrictedPatterns = getRestrictedPatterns(options);
|
|
const allowedImportTypeMatchers = [];
|
|
for (const restrictedPattern of restrictedPatterns) {
|
|
if (typeof restrictedPattern === 'object' &&
|
|
restrictedPattern.allowTypeImports) {
|
|
// Following how ignore is configured in the base rule
|
|
allowedImportTypeMatchers.push((0, ignore_1.default)({
|
|
allowRelativePaths: true,
|
|
ignoreCase: !restrictedPattern.caseSensitive,
|
|
}).add(restrictedPattern.group));
|
|
}
|
|
}
|
|
function isAllowedTypeImportPattern(importSource) {
|
|
return (
|
|
// As long as there's one matching pattern that allows type import
|
|
allowedImportTypeMatchers.some(matcher => matcher.ignores(importSource)));
|
|
}
|
|
function checkImportNode(node) {
|
|
if (node.importKind === 'type' ||
|
|
(node.specifiers.length > 0 &&
|
|
node.specifiers.every(specifier => specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
|
|
specifier.importKind === 'type'))) {
|
|
const importSource = node.source.value.trim();
|
|
if (!isAllowedTypeImportPath(importSource) &&
|
|
!isAllowedTypeImportPattern(importSource)) {
|
|
return rules.ImportDeclaration(node);
|
|
}
|
|
}
|
|
else {
|
|
return rules.ImportDeclaration(node);
|
|
}
|
|
}
|
|
return {
|
|
TSImportEqualsDeclaration(node) {
|
|
if (node.moduleReference.type ===
|
|
utils_1.AST_NODE_TYPES.TSExternalModuleReference &&
|
|
node.moduleReference.expression.type === utils_1.AST_NODE_TYPES.Literal &&
|
|
typeof node.moduleReference.expression.value === 'string') {
|
|
const synthesizedImport = {
|
|
...node,
|
|
type: utils_1.AST_NODE_TYPES.ImportDeclaration,
|
|
source: node.moduleReference.expression,
|
|
assertions: [],
|
|
attributes: [],
|
|
specifiers: [
|
|
{
|
|
...node.id,
|
|
type: utils_1.AST_NODE_TYPES.ImportDefaultSpecifier,
|
|
local: node.id,
|
|
},
|
|
],
|
|
};
|
|
return checkImportNode(synthesizedImport);
|
|
}
|
|
},
|
|
ImportDeclaration: checkImportNode,
|
|
'ExportNamedDeclaration[source]'(node) {
|
|
if (node.exportKind === 'type' ||
|
|
(node.specifiers.length > 0 &&
|
|
node.specifiers.every(specifier => specifier.exportKind === 'type'))) {
|
|
const importSource = node.source.value.trim();
|
|
if (!isAllowedTypeImportPath(importSource) &&
|
|
!isAllowedTypeImportPattern(importSource)) {
|
|
return rules.ExportNamedDeclaration(node);
|
|
}
|
|
}
|
|
else {
|
|
return rules.ExportNamedDeclaration(node);
|
|
}
|
|
},
|
|
ExportAllDeclaration: rules.ExportAllDeclaration,
|
|
};
|
|
},
|
|
});
|
|
//# sourceMappingURL=no-restricted-imports.js.map |