@sashar/eslint-plugin-fsd-paths
Version:
ESLint plugin for checking the correctness of import paths in FSD architecture
98 lines (84 loc) • 2.43 kB
JavaScript
;
const {isPathRelative} = require("../helpers");
const micromatch = require("micromatch");
const PUBLIC_ERROR = 'PUBLIC_ERROR';
const TESTING_PUBLIC_ERROR = 'TESTING_PUBLIC_ERROR';
module.exports = {
PUBLIC_ERROR,
TESTING_PUBLIC_ERROR,
meta: {
type: null,
docs: {
description: "Enforce that imports use the public API (index.ts or testing.ts) of feature slices",
recommended: false,
url: null,
},
fixable: 'code',
messages: {
[PUBLIC_ERROR]: 'Absolute import is allowed only from Public Api (index.ts)',
[TESTING_PUBLIC_ERROR]: 'Test data must be imported from Public Api (testing.ts)',
},
schema: [{
type: 'object',
properties: {
alias: {
type: 'string'
},
testFilesPatterns: {
type: 'array',
items: { type: "string" },
}
}
}],
},
create(context) {
const {
alias = '',
testFilesPatterns = []
} = context.options[0] ?? {};
const checkingLayers = {
pages: 'pages',
widgets: 'widgets',
entities: 'entities',
features: 'features',
}
return {
ImportDeclaration(node) {
const importPath = node.source.value;
const normalizedPath = alias
? importPath.replace(`${alias}/`, '')
: importPath
;
if (isPathRelative(normalizedPath)) {
return;
}
const segments = normalizedPath.split('/');
const layer = segments[0];
const slice = segments[1];
if (!checkingLayers[layer]) {
return;
}
const isImportFromPublicApi = segments.length > 2;
const isTestingImport = segments[2] === 'testing' && segments.length < 4;
if (isImportFromPublicApi && !isTestingImport) {
context.report({
node,
messageId: PUBLIC_ERROR,
fix: (fixer) => {
return fixer.replaceText(node.source, `'${alias}/${layer}/${slice}'`)
}
});
}
if (isTestingImport) {
const currentFile = context.getFilename();
const isTestingFile = testFilesPatterns.some(
pattern => micromatch.isMatch(currentFile, pattern)
);
if (!isTestingFile) {
context.report({node, messageId: TESTING_PUBLIC_ERROR});
}
}
}
};
},
};