eslint-plugin-fsd-arch-validator
Version:
Validate whether module imports within your project meet the requirements of FSD architecture
71 lines (59 loc) • 2.07 kB
JavaScript
const micromatch = require('micromatch');
const { isPathRelative } = require('../helpers');
const path = require("path");
const availableLayers = {
'entities': 'entities',
'features': 'features',
'widgets': 'widgets',
'pages': 'pages',
}
module.exports = {
meta: {
type: null, // `problem`, `suggestion`, or `layout`
docs: {
description: "Imports from another modules may only be through an interface - public api",
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' },
devFiles: { type: 'array' },
}
}
], // Add a schema if the rule has options
},
create(context) {
const { alias = '', devFiles = [] } = context.options[0] || {}
return {
ImportDeclaration(node) {
const value = node.source.value
const importTo = alias ? value.replace(`${alias}/`, '') : value;
if(isPathRelative(importTo)) {
return false;
}
const segments = importTo.split('/');
const layer = segments[0];
if (!availableLayers[layer]) {
return;
}
const isImportNotFromPublicAPI = segments.length > 2;
const isTestingPublicAPI = segments[2] === 'dev' && segments.length < 4;
if(isImportNotFromPublicAPI && !isTestingPublicAPI) {
context.report(node, 'Imports from another modules should only be from public API (index.ts).');
}
if(isTestingPublicAPI) {
const currentFilePath = context.getFilename();
const normalizedPath = path.toNamespacedPath(currentFilePath);
const isCurrentFileDev = devFiles.some(devFilePattern => micromatch.isMatch(normalizedPath, devFilePattern))
if (!isCurrentFileDev) {
context.report(node, 'Imports from another modules should only be from public API (dev.ts).');
}
}
}
};
},
};