npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

eslint-plugin-structural-police

v1.1.5

Published

eslint plugin to control file structure and imports

Downloads

14

Readme

RU | EN

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 аргументов:

  1. groups:array of object - Массив групп импортов (подробнее в пункте "Группы")
  2. behaviorRelatedComment:string - Вариант поведения комментариев, находящихся непосредственно перед импортов при использовании функции автофикса (флаг --fix). При значении link (default value) все комментарии перемещаются вместе с импортом. При значении remove все комментарии удаляются
  3. blankLineAfterEveryGroup:boolean - Нужно ли после каждой группы импортов вставлять пустую строку (default value: false)
  4. groupNamePrefix:string - Префикс необходимый, чтобы отличать обычные комментарии от названий групп импортов (default value: ' # '). Например: // # GroupName
  5. oldGroupNamePrefix:string - Префикс, необходимый при изменении настройки groupNamePrefix, чтобы удалить названия групп со старым префиксом
  6. withinGroupSort:array of string - Массив строк формирующих регулярные выражения, в порядке которых будут сортироваться пути импортов внутри групп. То есть передав ['^([A-Z]|[a-z])', '^[.]'] внутри группы будут идти сначала импорты начинающиеся с букв, а потом - с точки. При использовании этой настройки все импорты внутри группы будут отсортированы по алфавиту. Если нужно включить только сортировку по алфавиту, то нужно передать массив с одной регуляркой - ['^']
  7. customErrorMessages:object - Объект с колбэками, формирующими тексты ошибок (подробнее в пункте "Кастомные сообщения ошибок")
  8. 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, каждый из которых вызывается при разных проблемах:

  1. mustBeAfter вызывается, если нарушен порядок импортов
  2. blankLineDetected вызывается, если обнаружена лишняя пустая строка между импортами
  3. blankLineExpected вызывается, если после группы с blankLineAfter нет пустой строки
  4. needAddComment вызывается, если перед группой с name нет комментария с названием
  5. 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 аргументов:

  1. schema:object - Схема валидации импортов (подробнее в пункте "Схема")
  2. inheritance:boolean - Наследование правил. Если у дочернего узла нет собственных правил, то будут применены правила ближайшего родителя
  3. entryPoints:array of string - Массив путей до валидируемых файлов
  4. everywhereAllowed:array of string - Массив путей до файлов, импорт которых всегда доступен
  5. customErrorMessages:object - Объект с колбэками, формирующими тексты ошибок (подробнее в пункте "Кастомные сообщения ошибок")

Схема

Схема описывает структуру проекта, по которой линтер будет проверять корректность расположения файлов и возможность осуществления импортов.

В схеме могут использоваться 3 ключех слова:

  1. __rules__ - В данном объекте линтер будет искать правила для конкретного узла схемы
  2. __any__ - Разрешает любую структуру дочерниих файлов. Если __any__ установлен true, то линтер прекращает поиск правил глубже по схеме и применяет ко всем вложенным файлам уже найденые правила, если такие были
  3. __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, каждый из которых вызывается при разных проблемах:

  1. importDisallow вызывается, если в файле найден импорт из запрещенного правилами (схемой) источника
  2. missingFile вызывается, если проверяемый файл не описан в схеме
  3. 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 необязательных ключа:

  1. defaultAllowed:boolean - Импорт со всех адресов разрешен, если true. Запрещен, если false (default value: true)
  2. allowed:array of string - Массив разрешенных адресов для исключения из defaultAllowed = true
  3. disallowed:array of string - Массив запрещенных адресов для исключения из defaultAllowed = false

!!! Важно !!!

  1. На одном уровне вложенности может быть только одно ключевое слово __var__<variable_name>
  2. __var__ переменные не должны повторяться
  3. Если в узле отсутствуют правила и аргумент 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 запрещает использование дефолтных экспортов