UNPKG

eslint-plugin-almatvit-plugin

Version:

ESLint plugin for enforcing relative imports inside feature slices.

110 lines (88 loc) 2.98 kB
// /** // * @fileoverview safas // * @author Almavit // */ // "use strict"; //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ // /** @type {import('eslint').Rule.RuleModule} */ const path = require('path'); const { isPathRelative } = require('../helpers'); const micromatch = require('micromatch'); module.exports = { meta: { type: null, // `problem`, `suggestion`, or `layout` docs: { description: "safas", recommended: false, url: null, // URL to the documentation page for this rule }, fixable: null, // Or `code` or `whitespace` schema: [{ type: 'object', properties: { alias: { type: 'string', }, ignoreImportPatterns: { type: 'array', } }, }], // Add a schema if the rule has options messages: {}, // Add messageId and message }, create(context) { const layers = { 'app': ['pages', 'widgets', 'features', 'shared', 'entities'], 'pages': ['widgets', 'features', 'shared', 'entities'], 'widgets': ['features', 'shared', 'entities'], 'features': ['shared', 'entities'], 'entities': ['shared', 'entities'], 'shared': ['shared'], } const availableLayers = { 'app': 'app', 'entities': 'entities', 'features': 'features', 'shared': 'shared', 'pages': 'pages', 'widgets': 'widgets', } const { alias = '', ignoreImportPatterns = [] } = context.options[0] ?? {}; const getCurrentFileLayer = () => { const currentFilePath = context.getFilename(); const normalizedPath = path.toNamespacedPath(currentFilePath); const projectPath = normalizedPath?.split('src')[1]; const segments = projectPath?.split('\\') return segments?.[1]; } const getImportLayer = (value) => { const importPath = alias ? value.replace(`${alias}/`, '') : value; const segments = importPath?.split('/') return segments?.[0] } return { ImportDeclaration(node) { const importPath = node.source.value const currentFileLayer = getCurrentFileLayer() const importLayer = getImportLayer(importPath) if (isPathRelative(importPath)) { return; } if (!availableLayers[importLayer] || !availableLayers[currentFileLayer]) { return; } const isIgnored = ignoreImportPatterns.some(pattern => { return micromatch.isMatch(importPath, pattern) }); if (isIgnored) { return; } if (!layers[currentFileLayer]?.includes(importLayer)) { context.report(node, 'Слой может импортировать в себя только нижележащие слои (shared, entities, features, widgets, pages, app)'); } } }; }, };