eslint-plugin-export-scope
Version:
Don't leak LOCAL utils, states, components into the global scope
92 lines • 4.98 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.rule = exports.ruleName = void 0;
const utils_1 = require("@typescript-eslint/utils");
const checkIsImportable_1 = require("../checkIsImportable");
const validateScopeFileScopePath_1 = require("./validateScopeFileScopePath");
const typescript_1 = require("typescript");
const validateProgram_1 = require("./validateProgram");
const esLintUtils_1 = require("./esLintUtils");
exports.ruleName = "no-imports-outside-export-scope";
const createRule = utils_1.ESLintUtils.RuleCreator(() => "https://github.com/A-Shleifman/eslint-plugin-export-scope");
const errorMessages = {
exportScope: "Cannot import {{ identifier }} outside its export scope",
invalidPath: `Invalid scope path: "{{ identifier }}"`,
onlyParents: "Only parent dirs are allowed for @scope and @scopeDefault",
};
exports.rule = createRule({
name: exports.ruleName,
meta: {
type: "problem",
docs: {
description: "Disallows importing scoped exports outside their scope",
},
messages: errorMessages,
schema: [],
},
defaultOptions: [],
create(context) {
const services = utils_1.ESLintUtils.getParserServices(context);
if (!services.getSymbolAtLocation) {
throw new Error("Please make sure you have the latest version of `@typescript-eslint/parser` installed.");
}
const compilerOptions = services.program.getCompilerOptions();
const resolvePath = (relativePath) => (0, typescript_1.resolveModuleName)(relativePath, context.filename, compilerOptions, typescript_1.sys).resolvedModule?.resolvedFileName;
const checkNode = (node, exportName, relExportPath) => {
if (!relExportPath)
return;
const exportPath = resolvePath(relExportPath);
if (!(0, checkIsImportable_1.checkIsImportable)({ tsProgram: services.program, importPath: context.filename, exportPath, exportName })) {
context.report({
node,
messageId: "exportScope",
data: { identifier: exportName ? `'${exportName}'` : "module" },
});
}
};
const lintNode = (node, relExportPath) => {
const isPromise = node.type === utils_1.AST_NODE_TYPES.AwaitExpression && node.parent;
node = isPromise ? node.parent : node;
const { type } = node;
if (type === utils_1.AST_NODE_TYPES.Identifier) {
checkNode(node, node.name, relExportPath);
}
if (type === utils_1.AST_NODE_TYPES.MemberExpression && node.property.type === utils_1.AST_NODE_TYPES.Identifier) {
checkNode(node.property, node.property.name, relExportPath);
}
const lintObjectPattern = (node) => {
node.properties.forEach((property) => {
if (property.type === utils_1.AST_NODE_TYPES.Property && property.key.type === utils_1.AST_NODE_TYPES.Identifier) {
checkNode(property.key, property.key.name, relExportPath);
}
});
};
if (type === utils_1.AST_NODE_TYPES.VariableDeclarator && node.id.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
lintObjectPattern(node.id);
}
if (type === utils_1.AST_NODE_TYPES.ObjectPattern) {
lintObjectPattern(node);
}
if (type === utils_1.AST_NODE_TYPES.TSQualifiedName) {
checkNode(node.right, node.right.name, relExportPath);
}
};
return {
ImportSpecifier: (node) => "name" in node.imported && checkNode(node, node.imported.name, (0, esLintUtils_1.extractPathFromImport)(node.parent)),
ImportDefaultSpecifier: (node) => checkNode(node, "default", (0, esLintUtils_1.extractPathFromImport)(node.parent)),
ImportDeclaration: (node) => !node.specifiers.length && checkNode(node, undefined, (0, esLintUtils_1.extractPathFromImport)(node)),
// 👇 dynamic import of the whole module without accessing exports
ImportExpression: (node) => {
const relExportPath = (0, esLintUtils_1.extractPathFromImport)(node);
const parent = node.parent;
if (parent.parent?.type === utils_1.AST_NODE_TYPES.Program ||
(parent?.type === utils_1.AST_NODE_TYPES.AwaitExpression && parent.parent.parent?.type === utils_1.AST_NODE_TYPES.Program)) {
return checkNode(node, undefined, relExportPath);
}
},
Program: (node) => (0, validateProgram_1.validateProgram)(context, node, lintNode),
Literal: (node) => (0, validateScopeFileScopePath_1.validateScopeFileScopePath)(context, node),
};
},
});
//# sourceMappingURL=esLintRule.js.map
;