eslint-plugin-structural-police
v1.1.5
Published
eslint plugin to control file structure and imports
Downloads
11
Maintainers
Readme
structural-police
eslint plugin для контроля структуры файлов и импортов
Установка
npm i eslint-plugin-structural-police
Быстрый старт
// .eslintrc.[js|yml|json]
{
"plugins": [
// ... какие-то твои плагины
"structural-police"
],
"extends": [
// ... какие-то твои конфиги плагинов
// один из конфигов
"plugin:structural-police/recommended"
// или
"plugin:structural-police/featureSliced"
],
}
Правила плагина
import-order
Настройка
Правило import-order
принимает 8 аргументов:
groups
:array of object - Массив групп импортов (подробнее в пункте "Группы")behaviorRelatedComment
:string - Вариант поведения комментариев, находящихся непосредственно перед импортов при использовании функции автофикса (флаг --fix). При значенииlink
(default value) все комментарии перемещаются вместе с импортом. При значенииremove
все комментарии удаляютсяblankLineAfterEveryGroup
:boolean - Нужно ли после каждой группы импортов вставлять пустую строку (default value: false)groupNamePrefix
:string - Префикс необходимый, чтобы отличать обычные комментарии от названий групп импортов (default value: ' # '). Например:// # GroupName
oldGroupNamePrefix
:string - Префикс, необходимый при изменении настройкиgroupNamePrefix
, чтобы удалить названия групп со старым префиксомwithinGroupSort
:array of string - Массив строк формирующих регулярные выражения, в порядке которых будут сортироваться пути импортов внутри групп. То есть передав['^([A-Z]|[a-z])', '^[.]']
внутри группы будут идти сначала импорты начинающиеся с букв, а потом - с точки. При использовании этой настройки все импорты внутри группы будут отсортированы по алфавиту. Если нужно включить только сортировку по алфавиту, то нужно передать массив с одной регуляркой -['^']
customErrorMessages
:object - Объект с колбэками, формирующими тексты ошибок (подробнее в пункте "Кастомные сообщения ошибок")optimizedFix
:boolean - Если true (default value: false), то в начале файла добавляется ошибка аккумулятор, которая содержит фикс функцию, устраняющую все ошибки данного правила за один проход линта. Рекомендуется использовать при запуске с флагом--fix
, чтобы не запускать скрипт несколько раз для устранения всех ошибок
Группы
У каждого объекта группы есть 5 параметров:
name
. Если естьname
, то перед этой группой необходим комментарий с названием группыpriority
отвечает за приоритет разбора импортов по группам. То есть если импорт удовлетворяет условиям двух групп, то он будет размещен в групу с наивысшим приоритетом (default value: 1)blankLineAfter
отвечает за наличие пустой строки после группы (default value: false)importPathMatch
содержит регулярное выражение или строку для формирования регулярного выражения (без флагов), по которому проверяется импортируемый путьimportAbsPathMatch
содержит регулярное выражение или строку для формирования регулярного выражения (без флагов), по которому проверяется абсолютный путь до импортируемого файла. То есть находясь в файлеsrc/feature/index.ts
и импортируя из../ui/form.ts
, по регулярному выражениюimportAbsPathMatch
будет проверяться путьsrc/ui/form.ts
Пример
groups: [
{ priority: 0, importPathMatch: /^/, blankLineAfter: true },
{ name: 'actions', priority: 2, importAbsPathMatch: /Action/, blankLineAfter: false },
{ name: 'stores', priority: 2, importAbsPathMatch: /Store/ },
{ name: 'styles', priority: 1, importPathMatch: /.css$/, blankLineAfter: true },
]
Кастомные сообщения ошибок
Если есть желание изменить тексты ошибок выбрасываемых линтом, то можно сделать это, передав
в аргумент customErrorMessages
объект со своими колбэками.
В правиле есть три типа ошибок mustBeAfter
, blankLineDetected
, blankLineExpected
,
needAddComment
и needRemoveComment
, каждый из которых вызывается при разных проблемах:
mustBeAfter
вызывается, если нарушен порядок импортовblankLineDetected
вызывается, если обнаружена лишняя пустая строка между импортамиblankLineExpected
вызывается, если после группы сblankLineAfter
нет пустой строкиneedAddComment
вызывается, если перед группой сname
нет комментария с названиемneedRemoveComment
вызывается для неправильных названий групп
Ниже приведен объект с дефолтными колбэками, тут же можно посмотреть какие аргументы должны принимать колбэки
const defaultErrorMessages = {
mustBeAfter: ({ importPath, mustBeAfterImportPath }) =>
`This import must be after import from "${mustBeAfterImportPath}"`,
blankLineDetected: ({ importPath, groupName }) =>
`Must not be blank line after import from "${importPath}"`,
blankLineExpected: ({ importPath, groupName }) =>
`Need blank line after imports group "${groupName}"`,
needAddComment: ({ groupName, newComment }) =>
`Before imports group "${groupName}" must be comment with groups name "${newComment}"`,
needRemoveComment: () =>
`Need remove wrong groups name`,
}
import-permission-schema
Настройка
Правило import-permission-schema
принимает 5 аргументов:
schema
:object - Схема валидации импортов (подробнее в пункте "Схема")inheritance
:boolean - Наследование правил. Если у дочернего узла нет собственных правил, то будут применены правила ближайшего родителяentryPoints
:array of string - Массив путей до валидируемых файловeverywhereAllowed
:array of string - Массив путей до файлов, импорт которых всегда доступенcustomErrorMessages
:object - Объект с колбэками, формирующими тексты ошибок (подробнее в пункте "Кастомные сообщения ошибок")
Схема
Схема описывает структуру проекта, по которой линтер будет проверять корректность расположения файлов и возможность осуществления импортов.
В схеме могут использоваться 3 ключех слова:
__rules__
- В данном объекте линтер будет искать правила для конкретного узла схемы__any__
- Разрешает любую структуру дочерниих файлов. Если__any__
установленtrue
, то линтер прекращает поиск правил глубже по схеме и применяет ко всем вложенным файлам уже найденые правила, если такие были__var__<variable_name>
- При помощи такой конструкции можно обобщить несколько разноименных директорий с одинаковой внутренней структурой, чтобы исключить дублирование в схеме. Например в директории apps у нас лежит три приложения app-a, app-b и app-c. Если у первых двух одинаковая структура, то схему можно составить следующим образом:
apps: {
'app-c': {
// Какая-то схема
},
__var__similar_apps: {
// Какая-то другая схема
},
},
В данном случае проверка будет происходить следующим образом:
Поиск правил для файла apps/app-c/index.ts
: Зашли в apps
, зашли в app-c
,
нашли правила для index.ts
Поиск правил для файла apps/app-a/index.ts
: Зашли в apps
, не нашли объект
app-a
, поэтому зашли в первый попавшийся __var__<variable_name>
, если такой есть
Кастомные сообщения ошибок
Если есть желание изменить тексты ошибок выбрасываемых линтом, то можно сделать это, передав
в аргумент customErrorMessages
объект со своими колбэками.
В правиле есть три типа ошибок importDisallow
, missingFile
и missingRules
, каждый из
которых вызывается при разных проблемах:
importDisallow
вызывается, если в файле найден импорт из запрещенного правилами (схемой) источникаmissingFile
вызывается, если проверяемый файл не описан в схемеmissingRules
вызывается для проверяемого файла в схеме не найдены правила
Ниже приведен объект с дефолтными колбэками, тут же можно посмотреть какие аргументы должны принимать колбэки
const defaultErrorMessages = {
importDisallow: ({ filePath, importPath, absoluteImportPath }) =>
`Not allowed to import from "${absoluteImportPath}"`,
missingFile: ({ schemaPath, missingNode }) =>
`The file is not described in the schema. In "${schemaPath}" expected a node "${missingNode}"`,
missingRules: ({ schemaPath }) =>
`There is no set of rules in the "${schemaPath}"`,
}
Правила
Правила можно передать в любой узел схемы под ключем __rules__
. Правила содержат 3 необязательных ключа:
defaultAllowed
:boolean - Импорт со всех адресов разрешен, если true. Запрещен, если false (default value: true)allowed
:array of string - Массив разрешенных адресов для исключения изdefaultAllowed = true
disallowed
:array of string - Массив запрещенных адресов для исключения изdefaultAllowed = false
!!! Важно !!!
- На одном уровне вложенности может быть только одно ключевое слово
__var__<variable_name>
__var__
переменные не должны повторяться- Если в узле отсутствуют правила и аргумент inheritance выставлен на false (отключено наследование правил), то это приведет к ошибке
!!! Интересно !!!
Переменные, указанные при составлении дерева файлов можно использовать в написании правил.
apps: {
__var__similar_apps: {
featuers: {},
shared: {},
},
},
В нашей схеме есть переменная <similar_apps>, полученная при указании ключевого слова __var__
вместо названий приложений app-a, app-b. И мы хотим разрешить импорт из shared в
featuers, но только в рамках одного приложения (то есть в app-b/featuers нельзя сделать
импорт модуля из app-a/shared).
Настроить такие ограничения можно разместив следующие правила в объекте features
__rules__: {
defaultAllowed: false,
allowed: [
'apps/__var__similar_apps/shared',
],
},
Логика проверки путей работает таким образом, что она вместо __var__
переменных подставит узлы,
из пути проверяемого файла. То есть находясь в файле apps/app-a/featuers/index.ts
переменная __var__similar_apps, используемая в правилах будет заменена на app-a
, а
находясь в apps/app-b/featuers/index.ts
- на app-b
.
Проще говоря, переменная __var__<variable_name>
- это текущая директория для каждого файла
no-default-export
Правило no-default-export
запрещает использование дефолтных экспортов