eslint-plugin-tis-imports
Version:
Eslint plugin for precise control of architectural restrictions. FSD, public api, hierarchy of entities in the project.
98 lines (97 loc) • 4.92 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLayerImportsRule = exports.DEFAULT_ALIAS = exports.DEFAULT_CHECK_RELATIVE_PATH_LAYERS = exports.DEFAULT_LAYERS = void 0;
const path_1 = __importDefault(require("path"));
const utils_1 = require("../utils");
const layers_1 = require("../utils/layers");
exports.DEFAULT_LAYERS = ['app', 'pages', 'widgets', 'features', 'entities', 'shared'];
exports.DEFAULT_CHECK_RELATIVE_PATH_LAYERS = ['app', 'pages', 'widgets', 'features', 'entities'];
exports.DEFAULT_ALIAS = '~';
const getCachedOptions = (0, utils_1.createCachedOptions)((options) => {
const layers = options.layers ?? exports.DEFAULT_LAYERS;
const alias = options.alias ?? exports.DEFAULT_ALIAS;
const checkRelativePathLayers = options.checkRelativePathLayers ?? exports.DEFAULT_CHECK_RELATIVE_PATH_LAYERS;
return ({
...options,
layers,
alias,
checkRelativePathLayers,
publicApiEnabled: options.publicApiEnabled ?? false,
publicApiExcludeLayersSet: new Set(options.publicApiExcludeLayers ?? []),
checkRelativePathLayersSet: new Set(checkRelativePathLayers),
layersSet: new Set(layers),
layersOrderMap: (0, utils_1.createLayersOrderMap)(layers),
notStrictLayersSet: options.notStrictLayers ? new Set(options.notStrictLayers) : undefined,
});
});
const createLayerImportsRule = (args) => {
const { options, filename, report } = args;
const resultOptions = getCachedOptions(options);
const { alias, layersSet, notStrictLayersSet, layersOrderMap, publicApiEnabled, publicApiExcludeLayersSet, checkRelativePathLayersSet } = resultOptions;
const currentFilePath = filename;
const relativePath = path_1.default.relative(process.cwd(), currentFilePath);
// Layer by currentFile
const currentLayer = (0, utils_1.getLayer)({
filePath: relativePath,
layersSet,
});
const currentSubfolder = currentLayer ? (0, layers_1.getSubfolderAfterLayer)(relativePath, currentLayer) : null;
return {
ImportDeclaration(node) {
// Get all paths
const importPath = node.source.value;
const resolvedImportPath = (0, utils_1.normalizeFilePathFromImport)({ importPath: typeof importPath === 'string' ? importPath : undefined, alias, currentFilePath });
// Layer by currentImport
const importLayer = (0, utils_1.getLayer)({
filePath: resolvedImportPath,
layersSet,
});
if (!currentLayer || !importLayer || typeof importPath !== 'string' || !resolvedImportPath)
return;
const currentLayerOrder = layersOrderMap.get(currentLayer) ?? 0;
const importLayerOrder = layersOrderMap.get(importLayer) ?? 0;
const importSubfolder = (0, layers_1.getSubfolderAfterLayer)(resolvedImportPath, importLayer);
if (notStrictLayersSet && checkRelativePathLayersSet?.has(importLayer)) {
if (currentLayerOrder === importLayerOrder &&
notStrictLayersSet.has(currentLayer) &&
currentSubfolder === importSubfolder &&
!(0, utils_1.checkRelativePath)({ path: importPath })) {
report({
node,
messageId: 'sameLayerAlias',
data: { currentLayer },
});
}
}
if (importLayerOrder === currentLayerOrder && !notStrictLayersSet?.has(currentLayer) && currentSubfolder && importSubfolder && currentSubfolder !== importSubfolder) {
report({
node,
messageId: 'wrongDirection',
data: { importingLayer: importLayer, currentLayer },
});
}
if (importLayerOrder < currentLayerOrder) {
report({
node,
messageId: 'wrongDirection',
data: { importingLayer: importLayer, currentLayer },
});
}
if (publicApiEnabled && currentLayer !== importLayer && !publicApiExcludeLayersSet?.has(importLayer)) {
const innerLayerFolders = resolvedImportPath.split(`${importLayer}/`)[1];
const innerLayerFoldersLength = innerLayerFolders?.split('/').length ?? 0;
if (innerLayerFoldersLength > 1) {
report({
node,
messageId: 'publicApiError',
data: {},
});
}
}
},
};
};
exports.createLayerImportsRule = createLayerImportsRule;