UNPKG

eslint-plugin-no-barrel-files

Version:

ESLint plugin for reducing barrel-file usage in two ways:

213 lines 11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.__private__ = void 0; const utils_1 = require("@typescript-eslint/utils"); const minimatch_1 = require("minimatch"); const analysis_1 = require("./prefer-source-imports/analysis"); const autofix_1 = require("./prefer-source-imports/autofix"); const path_utils_1 = require("./prefer-source-imports/path-utils"); const resolution_1 = require("./prefer-source-imports/resolution"); function isNamedImportSpecifier(specifier) { return (specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === utils_1.AST_NODE_TYPES.Identifier && specifier.local.type === utils_1.AST_NODE_TYPES.Identifier); } function isSupportedImportSpecifier(specifier) { return specifier.type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier || isNamedImportSpecifier(specifier); } function shouldReportMissingTypeScript(_filename, options) { return (options === null || options === void 0 ? void 0 : options.tsconfig) !== false && !(0, resolution_1.hasTypeScriptModule)(); } // ESLint creates a rule instance for every file. Parsed barrel modules are // immutable for this rule's fixes, so share them across those instances. const sharedAnalysisCaches = (0, analysis_1.createAnalysisCaches)(); const preferSourceImports = { defaultOptions: [{}], meta: { type: 'suggestion', fixable: 'code', docs: { url: 'https://github.com/art0rz/eslint-plugin-no-barrel-files', description: 'prefer importing from source modules instead of barrel re-exports', }, schema: [ { type: 'object', properties: { fixStyle: { type: 'string', enum: ['auto', 'preserve-alias', 'relative'], }, ignore: { type: 'array', items: { type: 'string' }, }, tsconfig: { anyOf: [{ type: 'boolean' }, { type: 'string' }], }, paths: { type: 'object', additionalProperties: { anyOf: [ { type: 'string' }, { type: 'array', items: { type: 'string' }, }, ], }, }, }, additionalProperties: false, }, ], messages: { missingTypeScript: "prefer-source-imports requires the 'typescript' package when tsconfig resolution is enabled. Install 'typescript' in the consuming project or set 'tsconfig: false'.", preferSourceImport: "Import '{{name}}' directly from '{{source}}' instead of barrel '{{barrel}}'.", preferSourceImports: "Import directly from source modules instead of barrel '{{barrel}}'.", }, }, create(context) { const [options] = context.options; const sourceCode = context.sourceCode; const barrelExportCache = new Map(); const analysisCaches = sharedAnalysisCaches; const resolutionCaches = (0, resolution_1.createSharedResolutionCaches)(); const cwd = process.cwd(); const missingTypeScript = shouldReportMissingTypeScript(context.filename, options); return { Program(node) { if (!missingTypeScript) { return; } context.report({ node, messageId: 'missingTypeScript', }); }, ImportDeclaration(node) { var _a; if (missingTypeScript) { return; } if (!node.source.value || typeof node.source.value !== 'string' || node.specifiers.length === 0) { return; } if ((_a = options === null || options === void 0 ? void 0 : options.ignore) === null || _a === void 0 ? void 0 : _a.some(pattern => (0, minimatch_1.minimatch)(node.source.value, pattern))) { return; } const supportedSpecifiers = node.specifiers.filter(isSupportedImportSpecifier); if (supportedSpecifiers.length === 0) { return; } const importerFilename = context.filename; const barrelFilePath = (0, resolution_1.resolveImport)(options, resolutionCaches, importerFilename, node.source.value, cwd); if (!barrelFilePath) { return; } const barrelAnalysis = (0, resolution_1.getBarrelAnalysis)(options, barrelFilePath, barrelExportCache, resolutionCaches, analysisCaches, cwd); if (!barrelAnalysis) { return; } const matchedSpecifiers = []; supportedSpecifiers.forEach(specifier => { const specifierIsTypeOnly = specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier ? (0, autofix_1.isTypeOnlyImport)(node, specifier) : false; const importedName = specifier.type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier ? 'default' : specifier.imported.name; const reExportKey = (0, analysis_1.getReExportKey)(importedName, specifierIsTypeOnly); const explicitReExport = barrelAnalysis.explicitReExports.get(reExportKey); if (explicitReExport) { matchedSpecifiers.push({ preferredSourceSpecifier: (0, resolution_1.getPreferredSourceSpecifier)(options, importerFilename, node.source.value, explicitReExport, resolutionCaches.tsconfigInfo, cwd, resolutionCaches.tsconfigPaths), specifier, reExportTarget: explicitReExport, }); return; } const exportAllReExport = barrelAnalysis.exportAllReExports.get(reExportKey); if (!exportAllReExport) { return; } matchedSpecifiers.push({ preferredSourceSpecifier: (0, resolution_1.getPreferredSourceSpecifier)(options, importerFilename, node.source.value, exportAllReExport, resolutionCaches.tsconfigInfo, cwd, resolutionCaches.tsconfigPaths), specifier, reExportTarget: exportAllReExport, }); }); if (matchedSpecifiers.length === 0) { return; } const canAutoFix = matchedSpecifiers.every(({ preferredSourceSpecifier }) => preferredSourceSpecifier !== null) && matchedSpecifiers.length === node.specifiers.length && node.specifiers.every(isSupportedImportSpecifier); const autofix = canAutoFix ? (0, autofix_1.buildAutofix)(sourceCode, node, matchedSpecifiers) : null; if (autofix) { context.report({ node, messageId: 'preferSourceImports', data: { barrel: node.source.value, }, fix: autofix, }); return; } matchedSpecifiers.forEach(({ specifier, reExportTarget }) => { var _a; context.report({ node: specifier, messageId: 'preferSourceImport', data: { barrel: node.source.value, name: specifier.local.name, source: (_a = (0, resolution_1.getPreferredSourceSpecifier)(options, importerFilename, node.source.value, reExportTarget, resolutionCaches.tsconfigInfo, cwd, resolutionCaches.tsconfigPaths)) !== null && _a !== void 0 ? _a : reExportTarget.sourceSpecifier, }, }); }); }, }; }, }; exports.__private__ = { applyAliasTarget: path_utils_1.applyAliasTarget, buildAliasSpecifier: path_utils_1.buildAliasSpecifier, buildAutofix: autofix_1.buildAutofix, collectAllExportedBindings: analysis_1.collectAllExportedBindings, collectBarrelAnalysis: analysis_1.collectBarrelAnalysis, collectExportedBindings: analysis_1.collectExportedBindings, createAnalysisCaches: analysis_1.createAnalysisCaches, createResolutionCaches: resolution_1.createResolutionCaches, createSharedResolutionCaches: resolution_1.createSharedResolutionCaches, getBarrelAnalysis: resolution_1.getBarrelAnalysis, getManualAliasMappings: resolution_1.getManualAliasMappings, getTypeScriptModule: resolution_1.getTypeScriptModule, hasTypeScriptModule: resolution_1.hasTypeScriptModule, getMergeableImportDeclaration: autofix_1.getMergeableImportDeclaration, getPreferredSourceSpecifier: resolution_1.getPreferredSourceSpecifier, getReExportKey: analysis_1.getReExportKey, getReExportMeta: analysis_1.getReExportMeta, getTsconfigInfo: resolution_1.getTsconfigInfo, getTsconfigPath: resolution_1.getTsconfigPath, isNamedImportSpecifier, isSupportedImportSpecifier, isRelativePath: path_utils_1.isRelativePath, isTypeOnlyImport: autofix_1.isTypeOnlyImport, matchesAliasPattern: path_utils_1.matchesAliasPattern, normalizeModulePath: path_utils_1.normalizeModulePath, parseBarrelFile: analysis_1.parseBarrelFile, parseExportedBindings: analysis_1.parseExportedBindings, parseModule: analysis_1.parseModule, resolveImport: resolution_1.resolveImport, resolveModuleFile: path_utils_1.resolveModuleFile, resolveReExportTarget: analysis_1.resolveReExportTarget, resolveWithManualPaths: resolution_1.resolveWithManualPaths, resolveWithTsconfig: resolution_1.resolveWithTsconfig, reverseResolveManualAlias: resolution_1.reverseResolveManualAlias, reverseResolveTsconfigAlias: resolution_1.reverseResolveTsconfigAlias, setTypeScriptModuleLoaderForTests: resolution_1.setTypeScriptModuleLoaderForTests, shouldReportMissingTypeScript, serializeImportBinding: autofix_1.serializeImportBinding, serializeImportBindings: autofix_1.serializeImportBindings, toRelativeImportSpecifier: path_utils_1.toRelativeImportSpecifier, }; exports.default = preferSourceImports; //# sourceMappingURL=prefer-source-imports.js.map