UNPKG

eslint-plugin-stratified-design

Version:
283 lines (230 loc) 6.23 kB
# Require that lower-level modules be imported (lower-level-imports) This rule enforces the requirement for importing lower-level modules. Here's an explanation: - Functions in the same file within the same folder are considered to be at the same level. - Child folders are considered to be at a lower level than the parent folder. - Installed modules (node modules) are considered to be at the lowest level. However, you can modify this hierarchy using the `structure` option. This rule works correctly on POSIX systems, where the path segment separator is `/`. It will be updated to work well on Windows systems in the future. ### Options The syntax to specify the level structure is as follows: ```json { "stratified-design/lower-level-imports": [ "error", { "structure": ["layer1", "layer2", "layer3"] } ] } ``` In the folder array, the file or folder on the left is considered to be at a higher level than the one on the right. To designate a layer as an abstract barrier, set `barrier` to `true`: ```json { "stratified-design/lower-level-imports": [ "error", { "structure": ["layer1", { "name": "layer2", "barrier": true }, "layer3"] } ] } ``` A language layer can 'pass' any abstract barrier: ```json { "stratified-design/lower-level-imports": [ "error", { "structure": [ "layer1", { "name": "layer2", "barrier": true }, { "name": "layer3", "language": true } ] } ] } ``` For the 'abstract barrier,' refer to "[Grokking Simplicity](https://grokkingsimplicity.com)." To locate a node module in the structure, set `nodeModule` to `true`: ```json { "stratified-design/lower-level-imports": [ "error", { "structure": [ "layer1", { "name": "nodeModule", "nodeModule": true }, "layer3" ] } ] } ``` The default root directory is the current working directory. To change the root directory, use the `root` option: ```json { "stratified-design/lower-level-imports": [ "error", { "structure": ["layer1", "layer2", "layer3"], "root": "./src" } ] } ``` If the name of an imported module has an alias, register the alias using the `aliases` option: ```json { "stratified-design/lower-level-imports": [ "error", { "structure": ["layer1", "layer2", "layer3"], "aliases": { "@": "./src" } } ] } ``` If you want to register the level of a layer by 'number,' set the option `useLevelNumber` to `true`: ```json { "stratified-design/lower-level-imports": ["error", { "useLevelNumber": true }] } ``` The options `structure` and `useLevelNumber` can be used together. An `index.xxx` file can be the highest level layer of sibling files when the option `isIndexHighest` is set to `true`: ```json { "stratified-design/lower-level-imports": ["error", { "isIndexHighest": true }] } ``` You can register the files to apply the rule (`lower-level-imports`) using the `include` and `exclude` options: ```json { "stratified-design/lower-level-imports": [ "error", { "include": ["**/*.js"], "exclude": ["**/*.test.js"] } ] } ``` The default is as follows: ```json { "include": ["**/*.{js,ts,jsx,tsx}"], "exclude": ["**/*.{spec,test}.{js,ts,jsx,tsx}"] } ``` Imported modules are excluded from the rule (`lower-level-imports`) using the `excludeImports` option: ```json { "stratified-design/lower-level-imports": [ "error", { "excludeImports": ["**/*.css"] } ] } ``` Explicitly imported types are excluded using `ignoreType` option: ```json { "stratified-design/stratified-imports": ["error", { "ignoreType": true }] } ``` ```js import type { SomeType } from "./type"; // Explicitly imported types are excluded ``` ## Rule Details If a file structure is as follows: ``` src/ ┣ layer1.js ┣ layer2/ ┃ ┣ index.js ┃ ┣ file.js ┃ ┣ otherFile.js ┃ ┗ subFolder/ ┃ layer3/ ┃ ┣ entry.js ┃ ┣ 1 layer.js ┃ ┗ 2 layer.js ┗ layer4.js ``` Examples of **incorrect** code for this rule: ```js /* "lower-level-imports": ["error"] */ // ./src/layer1.js import { func } from "../layer2/file"; ``` ```js /* "lower-level-imports": ["error"] */ // ./src/layer2/file.js import { func } from "./otherFile"; ``` ```js /* "lower-level-imports": ["error", { "structure": ["layer1", "layer2"] }] */ // ./src/layer2/file.js import { func } from "../layer1"; ``` ```js /* "lower-level-imports": ["error", { "structure": ["layer1", { name: "layer2", barrier: true }, "layer3"] }] */ // ./src/layer1.js import { func } from "../layer3/entry"; ``` ```js /* "lower-level-imports": ["error", { "structure": ["layer1", { "name": "nodeModule", "nodeModule": true }, "layer3"], }] */ // ./src/layer3/entry.js import { func } from "nodeModule"; ``` ```js /* "lower-level-imports": ["error", { "useLevelNumber": true }}] */ // ./src/layer1.js import { func } from "layer3/1 layer"; ``` Examples of **correct** code for this rule: ```js /* "lower-level-imports": ["error"] */ // ./src/layer2/file.js import { func } from "./subFolder/file"; ``` ```js /* "lower-level-imports": ["error", { "structure": ["layer1", "layer2"] }] */ // ./src/layer1.js import { func } from "../layer2/file"; ``` ```js /* "lower-level-imports": ["error", { "structure": ["layer1", "layer2"], "alias": { "@/": "./src/" } }] */ // ./src/layer1.js import { func } from "@/layer2/file"; ``` ```js /* "lower-level-imports": ["error", { "useLevelNumber": true }] */ // ./src/layer3/1 layer.js import { func } from "./2 layer"; ``` ```js /* "lower-level-imports": ["error", { "useLevelNumber": true }] */ // ./src/layer3/entry.js import { func } from "./1 layer"; ``` ```js /* "lower-level-imports": ["error", { "structure": ["layer1", "layer3"], "useLevelNumber": true }] */ // ./src/layer.js import { func } from "../layer3/entry"; ``` ```js /* "lower-level-imports": ["error", { "isIndexHighest": true }] */ // ./src/layer2/index.js import { func } from "./file"; ``` ```js /* "lower-level-imports": ["error", { "structure": ["layer1", { name: "layer2", barrier: true }, "layer3", { name: "layer4", language: true }] }] */ // ./src/layer1.js import { func } from "./layer4"; ```