├── .eslintrc.js ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── build.yml │ ├── check-package-version.yml │ ├── publish-to-github.yml │ └── publish-to-npm.yml ├── .gitignore ├── .husky ├── .gitignore └── pre-commit ├── .vscode └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── docs ├── guides │ ├── how-to-migrate-from-v1-to-v2.md │ └── how-to-migrate-from-v3-to-v4.md └── rules │ ├── element-types.md │ ├── entry-point.md │ ├── external.md │ ├── no-ignored.md │ ├── no-private.md │ ├── no-unknown-files.md │ └── no-unknown.md ├── eslint-local-rules.js ├── eslint.config.mjs ├── index.js ├── jest.config.js ├── package-lock.json ├── package.json ├── renovate.json ├── resolver-legacy-alias └── index.js ├── sonar-project.properties ├── src ├── configs │ ├── recommended.js │ └── strict.js ├── constants │ ├── plugin.js │ ├── rules.js │ └── settings.js ├── core │ ├── cache.js │ ├── dependencyInfo.js │ └── elementsInfo.js ├── helpers │ ├── debug.js │ ├── messages.js │ ├── rules.js │ ├── settings.js │ ├── utils.js │ └── validations.js ├── index.js ├── rules-factories │ └── dependency-rule.js └── rules │ ├── element-types.js │ ├── entry-point.js │ ├── external.js │ ├── no-ignored.js │ ├── no-private.js │ ├── no-unknown-files.js │ └── no-unknown.js └── test ├── fixtures ├── base-pattern │ └── domains │ │ ├── domain-a │ │ ├── components │ │ │ ├── atoms │ │ │ │ ├── atom-a │ │ │ │ │ ├── AtomA.js │ │ │ │ │ └── index.js │ │ │ │ └── atom-b │ │ │ │ │ ├── AtomB.js │ │ │ │ │ └── index.js │ │ │ └── molecules │ │ │ │ ├── molecule-a │ │ │ │ ├── MoleculeA.js │ │ │ │ └── index.js │ │ │ │ └── molecule-b │ │ │ │ ├── MoleculeB.js │ │ │ │ └── index.js │ │ └── modules │ │ │ ├── module-a │ │ │ ├── ModuleA.js │ │ │ ├── components │ │ │ │ ├── atoms │ │ │ │ │ ├── atom-e │ │ │ │ │ │ ├── AtomE.js │ │ │ │ │ │ └── index.js │ │ │ │ │ └── atom-f │ │ │ │ │ │ ├── AtomF.js │ │ │ │ │ │ └── index.js │ │ │ │ └── molecules │ │ │ │ │ └── molecule-e │ │ │ │ │ ├── MoleculeE.js │ │ │ │ │ └── index.js │ │ │ └── index.js │ │ │ └── module-b │ │ │ ├── ModuleB.js │ │ │ ├── index.js │ │ │ └── modules │ │ │ ├── module-h │ │ │ ├── ModuleH.js │ │ │ ├── index.js │ │ │ └── modules │ │ │ │ └── module-j │ │ │ │ ├── ModuleJ.js │ │ │ │ └── index.js │ │ │ └── module-i │ │ │ ├── ModuleI.js │ │ │ └── index.js │ │ └── domain-b │ │ ├── components │ │ ├── atoms │ │ │ ├── atom-c │ │ │ │ ├── AtomC.js │ │ │ │ └── index.js │ │ │ └── atom-d │ │ │ │ ├── AtomD.js │ │ │ │ └── index.js │ │ └── molecules │ │ │ ├── molecule-c │ │ │ ├── MoleculeC.js │ │ │ └── index.js │ │ │ └── molecule-d │ │ │ ├── MoleculeD.js │ │ │ └── index.js │ │ └── modules │ │ ├── module-c │ │ ├── ModuleC.js │ │ └── index.js │ │ └── module-d │ │ ├── ModuleD.js │ │ ├── index.js │ │ └── modules │ │ ├── module-e │ │ ├── ModuleE.js │ │ ├── index.js │ │ └── modules │ │ │ └── module-g │ │ │ ├── ModuleG.js │ │ │ └── index.js │ │ └── module-f │ │ ├── ModuleF.js │ │ └── index.js ├── docs-examples │ ├── components │ │ ├── atoms │ │ │ ├── atom-a │ │ │ │ ├── AtomA.js │ │ │ │ └── index.js │ │ │ └── atom-b │ │ │ │ ├── AtomB.js │ │ │ │ └── index.js │ │ └── molecules │ │ │ ├── molecule-a │ │ │ ├── MoleculeA.js │ │ │ └── index.js │ │ │ └── molecule-b │ │ │ ├── MoleculeB.js │ │ │ └── index.js │ ├── foo.js │ ├── foo2.js │ ├── helpers │ │ ├── data │ │ │ ├── parse.js │ │ │ └── sort.js │ │ └── permissions │ │ │ └── roles.js │ ├── index.js │ └── modules │ │ ├── module-a │ │ ├── ModuleA.js │ │ └── index.js │ │ └── module-b │ │ ├── ModuleB.js │ │ ├── index.js │ │ └── modules │ │ ├── module-c │ │ ├── ModuleC.js │ │ ├── index.js │ │ └── modules │ │ │ └── module-e │ │ │ ├── ModuleE.js │ │ │ └── index.js │ │ └── module-d │ │ ├── ModuleD.js │ │ └── index.js ├── layered │ └── modules │ │ ├── module-a │ │ ├── components │ │ │ └── ComponentA.js │ │ ├── helpers.js │ │ └── index.js │ │ └── module-b │ │ ├── components │ │ └── ComponentB.js │ │ └── index.js ├── nestjs-example │ ├── app.module.js │ ├── cats │ │ ├── cats.controller.js │ │ ├── cats.module.js │ │ ├── cats.service.js │ │ ├── dto │ │ │ └── create-cat.dto.js │ │ ├── interfaces │ │ │ └── cats.interface.js │ │ └── models │ │ │ ├── persian-cat.model.js │ │ │ └── siamese-cat.dto.js │ ├── common │ │ ├── decorators │ │ │ └── roles.decorator.js │ │ ├── filters │ │ │ └── http-exception.filter.js │ │ └── guards │ │ │ └── roles.guards.js │ ├── core │ │ ├── core.controller.js │ │ ├── core.model.js │ │ ├── core.module.js │ │ └── interceptors │ │ │ ├── logging.interceptor.js │ │ │ └── transform.interceptor.js │ └── main.js ├── one-level │ ├── components │ │ ├── ComponentD │ │ │ ├── ComponentD.js │ │ │ ├── index.js │ │ │ └── module-a.js │ │ ├── component-a │ │ │ ├── ComponentA.js │ │ │ ├── components │ │ │ │ └── component-c │ │ │ │ │ ├── ComponentC.js │ │ │ │ │ ├── components │ │ │ │ │ ├── component-d │ │ │ │ │ │ ├── ComponentD.js │ │ │ │ │ │ └── index.js │ │ │ │ │ └── component-e │ │ │ │ │ │ ├── ComponentE.js │ │ │ │ │ │ └── index.js │ │ │ │ │ └── index.js │ │ │ ├── helpers │ │ │ │ └── helper-a │ │ │ │ │ ├── HelperA.js │ │ │ │ │ ├── helpers │ │ │ │ │ └── helper-b │ │ │ │ │ │ ├── HelperB.js │ │ │ │ │ │ └── index.js │ │ │ │ │ └── index.js │ │ │ └── index.js │ │ ├── component-b │ │ │ ├── Component.js │ │ │ ├── ComponentB.js │ │ │ ├── index.js │ │ │ └── main.js │ │ └── component-c │ │ │ ├── component-c.js │ │ │ └── index.js │ ├── foo │ │ ├── foo2 │ │ │ └── foo2.js │ │ └── index.js │ ├── helpers │ │ ├── helper-a │ │ │ ├── HelperA.js │ │ │ ├── index.js │ │ │ └── main.js │ │ ├── helper-b │ │ │ ├── HelperB.js │ │ │ ├── index.js │ │ │ └── main.js │ │ └── module-a │ │ │ └── index.js │ ├── module-a-helpers │ │ ├── helper-1 │ │ │ └── index.js │ │ └── helper-2 │ │ │ └── index.js │ ├── modules │ │ ├── ModuleC │ │ │ └── ModuleC.js │ │ ├── module-a │ │ │ ├── ModuleA.js │ │ │ └── index.js │ │ └── module-b │ │ │ ├── ModuleB.js │ │ │ └── index.js │ └── tsconfig.json ├── two-levels-with-private │ ├── components │ │ ├── atoms │ │ │ ├── atom-a │ │ │ │ ├── AtomA.js │ │ │ │ └── index.js │ │ │ └── atom-b │ │ │ │ ├── AtomB.js │ │ │ │ ├── index.js │ │ │ │ └── subfolder-1 │ │ │ │ ├── subfile-1.js │ │ │ │ └── subfolder-2 │ │ │ │ └── subfile-2.js │ │ ├── layouts │ │ │ ├── layout-a │ │ │ │ ├── LayoutA.js │ │ │ │ └── index.js │ │ │ └── layout-b │ │ │ │ ├── LayoutB.js │ │ │ │ └── index.js │ │ └── molecules │ │ │ ├── molecule-a │ │ │ ├── MoleculeA.js │ │ │ ├── components │ │ │ │ ├── atoms │ │ │ │ │ └── atom-c │ │ │ │ │ │ ├── AtomC.js │ │ │ │ │ │ └── index.js │ │ │ │ └── molecules │ │ │ │ │ └── molecule-c │ │ │ │ │ ├── MoleculeC.js │ │ │ │ │ ├── components │ │ │ │ │ └── molecules │ │ │ │ │ │ └── molecule-d │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── moleculeD.js │ │ │ │ │ └── index.js │ │ │ └── index.js │ │ │ └── molecule-b │ │ │ ├── MoleculeB.js │ │ │ └── index.js │ ├── helpers │ │ ├── helper-a │ │ │ ├── helpers │ │ │ │ └── helper-c │ │ │ │ │ ├── index.js │ │ │ │ │ └── main.js │ │ │ ├── index.js │ │ │ └── main.js │ │ └── helper-b │ │ │ ├── index.js │ │ │ └── main.js │ └── modules │ │ ├── domain-a │ │ ├── module-a │ │ │ ├── ModuleA.js │ │ │ ├── index.js │ │ │ ├── subfolder-1 │ │ │ │ ├── subfile-1.js │ │ │ │ └── subfolder-2 │ │ │ │ │ ├── ModuleA.js │ │ │ │ │ └── subfile-2.js │ │ │ └── submodules │ │ │ │ └── module-c │ │ │ │ ├── ModuleC.js │ │ │ │ ├── index.js │ │ │ │ └── submodules │ │ │ │ └── module-d │ │ │ │ ├── ModuleD.js │ │ │ │ ├── index.js │ │ │ │ └── subfolder-1 │ │ │ │ └── subfile-1.js │ │ └── module-b │ │ │ ├── ModuleB.js │ │ │ └── index.js │ │ ├── domain-b │ │ ├── module-a │ │ │ ├── ModuleA.js │ │ │ └── index.js │ │ └── module-b │ │ │ ├── ModuleB.js │ │ │ └── index.js │ │ └── pages │ │ ├── page-a │ │ ├── ModuleA.js │ │ ├── PageA.js │ │ └── index.js │ │ └── page-b │ │ ├── PageB.js │ │ └── index.js └── two-levels │ ├── components │ ├── atoms │ │ ├── atom-a │ │ │ ├── AtomA.js │ │ │ └── index.js │ │ └── atom-b │ │ │ ├── AtomB.js │ │ │ ├── index.js │ │ │ └── subfolder-1 │ │ │ ├── subfile-1.js │ │ │ └── subfolder-2 │ │ │ └── subfile-2.js │ ├── layouts │ │ ├── layout-a │ │ │ ├── LayoutA.js │ │ │ └── index.js │ │ └── layout-b │ │ │ ├── LayoutB.js │ │ │ └── index.js │ └── molecules │ │ ├── molecule-a │ │ ├── MoleculeA.js │ │ └── index.js │ │ └── molecule-b │ │ ├── MoleculeB.js │ │ └── index.js │ ├── helpers │ ├── helper-a │ │ ├── index.js │ │ └── main.js │ └── helper-b │ │ ├── index.js │ │ └── main.js │ └── modules │ ├── domain-a │ ├── module-a │ │ ├── ModuleA.js │ │ ├── index.js │ │ └── subfolder-1 │ │ │ ├── subfile-1.js │ │ │ └── subfolder-2 │ │ │ ├── ModuleA.js │ │ │ └── subfile-2.js │ └── module-b │ │ ├── ModuleB.js │ │ └── index.js │ ├── domain-b │ ├── module-a │ │ ├── ModuleA.js │ │ └── index.js │ └── module-b │ │ ├── ModuleB.js │ │ └── index.js │ └── pages │ ├── page-a │ ├── ModuleA.js │ ├── PageA.js │ └── index.js │ └── page-b │ ├── PageB.js │ └── index.js ├── rules ├── base-pattern │ └── element-types.spec.js ├── docs-examples │ ├── element-types.spec.js │ ├── entry-point.spec.js │ ├── external.spec.js │ ├── no-ignored.spec.js │ ├── no-private.spec.js │ ├── no-unknown-files.spec.js │ └── no-unknown.spec.js ├── layered │ └── entry-point.spec.js ├── nestjs-example │ └── element-types.spec.js ├── one-level │ ├── element-types-dependency-nodes.spec.js │ ├── element-types-import-kind.spec.js │ ├── element-types-template.spec.js │ ├── element-types.spec.js │ ├── entry-point-import-kind.spec.js │ ├── entry-point-template.spec.js │ ├── entry-point.spec.js │ ├── external-dependency-nodes.spec.js │ ├── external-import-kind.spec.js │ ├── external-template.spec.js │ ├── external.spec.js │ ├── invalid-settings.spec.js │ ├── no-ignored.spec.js │ ├── no-private.spec.js │ ├── no-unknown-files.spec.js │ └── no-unknown.spec.js └── two-levels │ ├── element-types.spec.js │ ├── entry-point.spec.js │ ├── external.spec.js │ └── no-private.spec.js ├── src ├── .eslintrc.json └── index.spec.js └── support ├── helpers.js └── messages.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | es6: true, 6 | }, 7 | parserOptions: { 8 | ecmaVersion: 2022, 9 | }, 10 | extends: ["prettier"], 11 | plugins: ["prettier", "eslint-plugin-local-rules"], 12 | rules: { 13 | "prettier/prettier": [ 14 | "error", 15 | { 16 | printWidth: 99, 17 | parser: "flow", 18 | }, 19 | ], 20 | "no-shadow": [2, { builtinGlobals: true, hoist: "all" }], 21 | "no-undef": "error", 22 | "no-unused-vars": ["error", { vars: "all", args: "after-used", ignoreRestSiblings: false }], 23 | }, 24 | overrides: [ 25 | { 26 | files: ["src/**/*.js"], 27 | settings: { 28 | "boundaries/dependency-nodes": ["require", "import", "dynamic-import", "export"], 29 | "boundaries/elements": [ 30 | { 31 | type: "config", 32 | mode: "file", 33 | pattern: ["src/configs/*.js", "(package.json)"], 34 | capture: ["name"], 35 | }, 36 | { 37 | type: "constants", 38 | mode: "file", 39 | pattern: "src/constants/*.js", 40 | capture: ["name"], 41 | }, 42 | { 43 | type: "core", 44 | mode: "file", 45 | pattern: "src/core/*.js", 46 | capture: ["name"], 47 | }, 48 | { 49 | type: "helper", 50 | mode: "file", 51 | pattern: "src/helpers/*.js", 52 | capture: ["name"], 53 | }, 54 | { 55 | type: "rule", 56 | mode: "file", 57 | pattern: "src/rules/*.js", 58 | capture: ["name"], 59 | }, 60 | { 61 | type: "rule-factory", 62 | mode: "file", 63 | pattern: "src/rules-factories/*.js", 64 | capture: ["name"], 65 | }, 66 | { 67 | type: "plugin", 68 | mode: "full", 69 | pattern: ["src/index.js"], 70 | }, 71 | ], 72 | }, 73 | rules: { 74 | "local-rules/boundaries/element-types": [ 75 | 2, 76 | { 77 | default: "disallow", 78 | rules: [ 79 | { 80 | from: "plugin", 81 | allow: ["constants", "config", "rule"], 82 | }, 83 | { 84 | from: "config", 85 | allow: ["constants", "config"], 86 | }, 87 | { 88 | from: "constants", 89 | allow: ["constants"], 90 | }, 91 | { 92 | from: "core", 93 | allow: ["constants", "helper", "core"], 94 | }, 95 | { 96 | from: "helper", 97 | allow: ["constants", "helper"], 98 | }, 99 | { 100 | from: "rule", 101 | allow: ["constants", "helper", "core", "rule-factory"], 102 | }, 103 | { 104 | from: "rule-factory", 105 | allow: ["constants", "helper", "core"], 106 | }, 107 | ], 108 | }, 109 | ], 110 | "local-rules/boundaries/no-unknown": [2], 111 | "local-rules/boundaries/no-unknown-files": [2], 112 | }, 113 | }, 114 | ], 115 | }; 116 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | First off, thanks for taking the time to contribute! 4 | 5 | The following is a set of guidelines for contributing to this project. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. 6 | 7 | #### Table Of Contents 8 | 9 | * [Code of Conduct](#code-of-conduct) 10 | * [Project governance](#project-governance) 11 | * [Rules](#rules) 12 | * [Releases](#releases) 13 | * [Changes to this arrangement](#changes-to-this-arrangement) 14 | * [Pull Requests](#pull-requests) 15 | * [Styleguides](#styleguides) 16 | * [Git Commit Messages](#git-commit-messages) 17 | * [JavaScript Styleguide](#javascript-styleguide) 18 | * [Tests Styleguide](#tests-styleguide) 19 | * [Developer's certificate of origin](#developers-certificate-of-origin) 20 | 21 | ## Code of Conduct 22 | 23 | This project and everyone participating in it is governed by the [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. 24 | 25 | ## Project Governance 26 | 27 | Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. 28 | 29 | ### Rules 30 | 31 | There are a few basic ground-rules for contributors: 32 | 33 | 1. **No `--force` pushes** or modifying the Git history in any way. 34 | 2. **All modifications** should be subject to a **pull request** to solicit feedback from other contributors. The base branch of the pull request should correspond with the assigned "release milestone" of the related issue. When an issue is created, it will be prioritized and a "release milestone" will be assigned to it, at the criteria of contributors. A branch will be created from master for that release milestone, and all related issues should be merged into it, until is ready to declare a formal release. 35 | 3. **All changes** to this project will be documented in the GHANGELOG.md file. 36 | 37 | ### Releases 38 | 39 | Declaring formal releases remains the prerogative of the project maintainer. 40 | 41 | ### Changes to this arrangement 42 | 43 | This document may also be subject to pull-requests or changes by contributors where you believe you have something valuable to add or change. 44 | 45 | ## Pull Requests 46 | 47 | * Fill in [the required template](PULL_REQUEST_TEMPLATE.md). 48 | * Do not include issue numbers in the PR title. 49 | * Follow the [JavaScript styleguide](#javascript-styleguide). 50 | * Follow the [Tests styleguide](#tests-styleguide). 51 | * All enhancements and bug fixes must be accompanied with all needed new related regression test. 52 | * Coverage of unit tests must remain 100%. 53 | * Run tests often. Tests are ran automatically with Travis when you push, but you still need to run them locally before pushing. 54 | * Document new features, or update documentation if changes affect to it. 55 | * End all files with a newline. 56 | * Place requires in the following order: 57 | * Built in Node Modules (such as `path`) 58 | * NPM Modules (such as `lodash`) 59 | * Local Modules (using relative paths) 60 | 61 | ## Styleguides 62 | 63 | ### Git Commit Messages 64 | 65 | * Use [semmantic commit](https://gist.github.com/joshbuchea/6f47e86d2510bce28f8e7f42ae84c716) 66 | 67 | ### JavaScript Styleguide 68 | 69 | All JavaScript must adhere to the style defined in the `.eslintrc.json` file. 70 | 71 | ### Tests Styleguide 72 | 73 | - Fail tests first. How do you know if it is actually testing anything if the assert never failed? 74 | - Treat `describe` as a noun or situation (Situations usually start with "when"). 75 | - Treat `it` as a statement about state or how an operation changes state. Usually, all `it` should start with "should". 76 | - Prefer fewer asserts per `it`. 77 | - Prefer one file for all specs of a javascript file, but, if it grows too much, split it into many files adding a sufix describing the behavior being tested in it (`file.behavior.js`) 78 | 79 | #### Example 80 | 81 | ```js 82 | describe("a dog", () => { 83 | describe("when is happy", () => { 84 | it("should wags its tail", () => { 85 | expect(dog.tail.moving).to.be.true(); 86 | }); 87 | }); 88 | }); 89 | ``` 90 | 91 | ## Developer's Certificate of Origin 92 | 93 | By making a contribution to this project, I certify that: 94 | 95 | - (a) The contribution was created in whole or in part by me and I have the right to 96 | submit it under the open source license indicated in the file; or 97 | 98 | - (b) The contribution is based upon previous work that, to the best of my knowledge, is 99 | covered under an appropriate open source license and I have the right under that license 100 | to submit that work with modifications, whether created in whole or in part by me, under 101 | the same open source license (unless I am permitted to submit under a different 102 | license), as indicated in the file; or 103 | 104 | - (c) The contribution was provided directly to me by some other person who certified 105 | (a), (b) or (c) and I have not modified it. 106 | 107 | - (d) I understand and agree that this project and the contribution are public and that a 108 | record of the contribution (including all personal information I submit with it, 109 | including my sign-off) is maintained indefinitely and may be redistributed consistent 110 | with this project or the open source license(s) involved. 111 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **Logs** 17 | If applicable, add logs to help explain your problem. 18 | 19 | ** Operating system, Node.js an npm versions, and eslint version (please complete the following information):** 20 | - OS: [e.g. Ubuntu 18.04] 21 | - Node.js: [e.g. 8.11.1] 22 | - npm: [e.g. 5.6.0] 23 | - ESLint: [e.g. v7.2.0] 24 | 25 | **Additional context** 26 | Add any other context about the problem here. 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or examples about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **IMPORTANT: Please do not create a Pull Request without creating an issue first.** 2 | 3 | *Any change needs to be discussed before proceeding. Failure to do so may result in the rejection of the pull request.* 4 | 5 | Please provide enough information so that others can review your pull request: 6 | 7 | Explain the **details** for making this change. What existing problem does the pull request solve? 8 | 9 | **Closing issues** 10 | 11 | Put `closes #XXXX` in your comment to auto-close the issue that your PR fixes. 12 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | on: 3 | push: 4 | branches: 5 | - master 6 | - release 7 | pull_request: 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | jobs: 12 | test: 13 | runs-on: ubuntu-latest 14 | strategy: 15 | matrix: 16 | node: ["18.20.3", "20.13.1", "22.2.0"] 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | - name: Use Node.js 21 | uses: actions/setup-node@v4 22 | with: 23 | node-version: ${{ matrix.node }} 24 | cache: "npm" 25 | - name: Install dependencies 26 | run: npm ci 27 | - name: Lint 28 | run: npm run lint 29 | - name: Test unit 30 | run: npm run test:unit 31 | - name: Upload test results 32 | uses: actions/upload-artifact@v4 33 | with: 34 | name: coverage-${{ matrix.node }} 35 | path: coverage 36 | retention-days: 1 37 | test-windows: 38 | runs-on: windows-2022 39 | strategy: 40 | matrix: 41 | node: ["18.20.3", "20.13.1", "22.2.0"] 42 | steps: 43 | - name: Checkout 44 | uses: actions/checkout@v4 45 | - name: Use Node.js 46 | uses: actions/setup-node@v4 47 | with: 48 | node-version: ${{ matrix.node }} 49 | cache: "npm" 50 | - name: Install dependencies 51 | run: npm ci --ignore-scripts 52 | env: 53 | HUSKY_SKIP_INSTALL: 1 54 | - name: Test unit 55 | run: npm run test:unit 56 | quality: 57 | runs-on: ubuntu-latest 58 | needs: test 59 | steps: 60 | - name: Checkout 61 | uses: actions/checkout@v4 62 | with: 63 | fetch-depth: 0 64 | - name: Download test results 65 | uses: actions/download-artifact@v4 66 | with: 67 | name: coverage-18.20.3 68 | path: coverage 69 | - name: Coveralls 70 | uses: coverallsapp/github-action@master 71 | with: 72 | github-token: ${{ secrets.GITHUB_TOKEN }} 73 | - name: SonarCloud Scan 74 | uses: sonarsource/sonarcloud-github-action@master 75 | if: env.SONAR_TOKEN != '' 76 | env: 77 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 78 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 79 | -------------------------------------------------------------------------------- /.github/workflows/check-package-version.yml: -------------------------------------------------------------------------------- 1 | name: check-package-version 2 | on: 3 | pull_request: 4 | branches: 5 | - master 6 | concurrency: 7 | group: ${{ github.workflow }}-${{ github.ref }} 8 | cancel-in-progress: true 9 | jobs: 10 | check-package-version: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | - name: Get NPM version is new 16 | id: check 17 | uses: EndBug/version-check@v2.1.4 18 | with: 19 | diff-search: true 20 | file-name: ./package.json 21 | file-url: https://unpkg.com/eslint-plugin-boundaries@latest/package.json 22 | static-checking: localIsNew 23 | - name: Check version is new 24 | if: steps.check.outputs.changed != 'true' 25 | run: | 26 | echo "Version not changed" 27 | exit 1 28 | - name: Get NPM version 29 | id: package-version 30 | uses: martinbeentjes/npm-get-version-action@v1.3.1 31 | - name: Check Changelog version 32 | id: changelog_reader 33 | uses: mindsers/changelog-reader-action@v2.2.3 34 | with: 35 | version: ${{ steps.package-version.outputs.current-version }} 36 | path: ./CHANGELOG.md 37 | - name: Read version from Sonar config 38 | id: sonar-version 39 | uses: christian-draeger/read-properties@1.1.1 40 | with: 41 | path: './sonar-project.properties' 42 | properties: 'sonar.projectVersion' 43 | - name: Check Sonar version 44 | if: steps.sonar-version.outputs.sonar-projectVersion != steps.package-version.outputs.current-version 45 | run: | 46 | echo "Version not changed" 47 | exit 1 48 | -------------------------------------------------------------------------------- /.github/workflows/publish-to-github.yml: -------------------------------------------------------------------------------- 1 | name: publish-to-github 2 | on: 3 | release: 4 | types: [created] 5 | jobs: 6 | publish: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | # Setup .npmrc file to publish to GitHub Packages 11 | - uses: actions/setup-node@v4 12 | with: 13 | node-version: '20.x' 14 | registry-url: 'https://npm.pkg.github.com' 15 | # Defaults to the user or organization that owns the workflow file 16 | scope: '@javierbrea' 17 | - uses: MerthinTechnologies/edit-json-action@v1 18 | with: 19 | filename: './package.json' 20 | key: 'name' 21 | value: '@javierbrea/eslint-plugin-boundaries' 22 | - run: npm ci 23 | - run: npm publish 24 | env: 25 | NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | -------------------------------------------------------------------------------- /.github/workflows/publish-to-npm.yml: -------------------------------------------------------------------------------- 1 | name: publish-to-npm 2 | on: 3 | release: 4 | types: [created] 5 | jobs: 6 | publish: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | - uses: actions/setup-node@v4 11 | with: 12 | node-version: '20.x' 13 | registry-url: 'https://registry.npmjs.org/' 14 | - run: npm ci 15 | - run: npm publish 16 | env: 17 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | #environment variables 4 | .env 5 | 6 | # dependencies 7 | /node_modules 8 | 9 | # tests 10 | /coverage 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | 23 | # ides 24 | .idea 25 | .vs 26 | .vscode 27 | 28 | # stryker temp files 29 | /reports 30 | .stryker-tmp 31 | stryker.conf.local.js 32 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npm run lint-staged 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "sonarlint.connectedMode.project": { 3 | "connectionId": "javierbrea", 4 | "projectKey": "javierbrea_eslint-plugin-boundaries" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Javier Brea 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/guides/how-to-migrate-from-v3-to-v4.md: -------------------------------------------------------------------------------- 1 | # How to migrate from v3.x to v4.x 2 | 3 | ## Table of Contents 4 | 5 | - [Breaking changes](#breaking-changes) 6 | - [How to migrate](#how-to-migrate) 7 | 8 | ## Breaking changes 9 | 10 | There is only one breaking change in the v4.0.0 release. We've fixed the bug that caused ESLint to incorrectly mark the error position for multiline imports. 11 | 12 | Previous behavior: 13 | 14 | ```js 15 | import { 16 | // ----^ (start of the error) 17 | ComponentA 18 | } from './components/component-a'; 19 | // -----------------------------^ (end of the error) 20 | ``` 21 | 22 | Fixed behavior: 23 | 24 | ```js 25 | import { 26 | ComponentA 27 | } from './components/component-a'; 28 | // ----^ (start) ---------------^ (end) 29 | ``` 30 | 31 | ## How to migrate 32 | 33 | You need to adjust your `eslint-disable-next-line` directives to match the new position. 34 | 35 | For example, this directive: 36 | 37 | ```js 38 | // eslint-disable-next-line 39 | import { 40 | ComponentA 41 | } from './components/component-a'; 42 | ``` 43 | 44 | Should be moved here: 45 | 46 | ```js 47 | import { 48 | ComponentA 49 | // eslint-disable-next-line 50 | } from './components/component-a'; 51 | ``` -------------------------------------------------------------------------------- /docs/rules/no-ignored.md: -------------------------------------------------------------------------------- 1 | # boundaries/no-ignored 2 | 3 | > Prevent importing ignored files from recognized elements 4 | 5 | ## Rule details 6 | 7 | It checks `import` statements to local files. If the imported file is marked as ignored in the plugin settings, the `import` will be notified as an error in files recognized as "elements". 8 | 9 | ### Options 10 | 11 | ``` 12 | "boundaries/no-ignored": [] 13 | ``` 14 | 15 | * `enabled`: for enabling the rule. 0=off, 1=warn, 2=error. 16 | 17 | ##### Options example 18 | 19 | ```jsonc 20 | { 21 | "rules": { 22 | "boundaries/no-ignored": [2] 23 | } 24 | } 25 | ``` 26 | 27 | ### Settings 28 | 29 | Examples in the next sections are based on the previous options example and these files and settings. 30 | 31 | ```txt 32 | src/ 33 | ├── helpers/ 34 | │ ├── data/ 35 | │ │ ├── sort.js 36 | │ │ └── parse.js 37 | │ └── permissions/ 38 | │ └── roles.js 39 | │ 40 | ├── foo.js 41 | └── index.js 42 | ``` 43 | 44 | ```jsonc 45 | { 46 | "settings": { 47 | "boundaries/include": ["src/**/*.js"], 48 | "boundaries/ignore": ["src/foo.js"], 49 | "boundaries/elements": [ 50 | { 51 | "type": "helpers", 52 | "pattern": "helpers/*/*.js", 53 | "mode": "file", 54 | "capture": ["category", "elementName"] 55 | } 56 | ] 57 | } 58 | } 59 | ``` 60 | 61 | ### Examples of **incorrect** code for this rule: 62 | 63 | _`foo.js` file is ignored, so it can't be imported by helpers_ 64 | 65 | ```js 66 | // src/helpers/data/sort.js 67 | import foo from "../../foo" 68 | ``` 69 | 70 | ### Examples of **correct** code for this rule: 71 | 72 | _`index.js` file is not recognized as any known element type, so it can import `foo.js`_ 73 | 74 | ```js 75 | // src/index.js 76 | import foo from "./foo" 77 | ``` 78 | 79 | ## Further reading 80 | 81 | Read [how to configure the `boundaries/elements` setting](../../README.md#global-settings) to assign an element type to each project's file. 82 | -------------------------------------------------------------------------------- /docs/rules/no-private.md: -------------------------------------------------------------------------------- 1 | # boundaries/no-private 2 | 3 | > Prevent importing private elements of another element 4 | 5 | ## Rule details 6 | 7 | This rule follow the next principles: 8 | 9 | * An element becomes private when it is under another element. 10 | * Private elements can't be used by anyone except its parent. _(and any other descendant of the parent when `allowUncles` option is enabled)_ 11 | * Private elements can import public elements. 12 | * Private elements can import another private element when both have the same parent _("brother elements")_ 13 | * Private elements can import another private element if it is a direct child of a common ancestor, and the `allowUncles` option is enabled. 14 | 15 | ### Options 16 | 17 | ``` 18 | "boundaries/no-private": [, { "allowUncles": , "message": }] 19 | ``` 20 | 21 | * `enabled`: for enabling the rule. 0=off, 1=warn, 2=error. 22 | * `allowUncles`: Optional. If set to `false`, it disallows importing "uncle elements". Default is `true`. 23 | * `message`: Custom message for the rule errors. Note that __the rule default message provides enough information about why the error was produced__, so you should define a custom message only if you are sure about what you are doing. Read ["error messages"](#error-messages) for further information. 24 | 25 | ##### Options example 26 | 27 | ```jsonc 28 | { 29 | "rules": { 30 | "boundaries/no-private": [2, { "allowUncles": true }] 31 | } 32 | } 33 | ``` 34 | 35 | ### Settings 36 | 37 | Examples in the next sections are based on the previous options example and these files and settings. 38 | 39 | ```txt 40 | src/ 41 | └── modules/ 42 | ├── module-a/ 43 | │ ├── index.js 44 | │ └── ModuleA.js 45 | └── module-b/ 46 | ├── index.js 47 | ├── ModuleB.js 48 | └── modules 49 | ├── module-c 50 | │ ├── index.js 51 | │ ├── ModuleC.js 52 | │ └── modules 53 | │ └── module-e 54 | │ ├── index.js 55 | │ └── ModuleE.js 56 | └── module-d 57 | ├── index.js 58 | └── ModuleD.js 59 | ``` 60 | 61 | ```jsonc 62 | { 63 | "settings": { 64 | "boundaries/elements": [ 65 | { 66 | "type": "modules", 67 | "pattern": "modules/*", 68 | "mode": "folder" 69 | } 70 | ], 71 | "import/resolver": { 72 | "babel-module": {} 73 | } 74 | } 75 | } 76 | ``` 77 | 78 | > Some of the next examples are written as is the project has configured a babel alias for the folder `src/modules`. This is made for better readability of the examples, but it would work also with relative paths. You can configure the plugin to recognize babel aliases [using `eslint-import-resolver-babel-module` as a resolver](../../README.md#resolvers), as you can see in the settings example. 79 | 80 | ### Examples of **incorrect** code for this rule: 81 | 82 | _`module-a` can't import `module-c` because it is child of `module-b`_ 83 | 84 | ```js 85 | // src/modules/module-a/moduleA.js 86 | import ModuleC from 'modules/module-b/modules/module-c' 87 | ``` 88 | 89 | _`module-b` can't import `module-e` because it is child of `module-c` (even when it is his grandchild)_ 90 | 91 | ```js 92 | // src/modules/module-b/moduleB.js 93 | import ModuleE from './modules/module-c/modules/module-e' 94 | ``` 95 | 96 | _`module-e` can't import `module-d` when `allowUncles` option is disabled_ 97 | 98 | ```js 99 | // src/modules/module-b/modules/module-c/modules/module-e/ModuleE 100 | import ModuleD from 'modules/module-b/modules/module-d' 101 | ``` 102 | 103 | ### Examples of **correct** code for this rule: 104 | 105 | _`module-b` can import `module-c` because it is his direct child_ 106 | 107 | ```js 108 | // src/modules/module-b/ModuleB.js 109 | import ModuleC from './modules/module-c' 110 | ``` 111 | 112 | _`module-c` can import `module-a` because it is public_ 113 | 114 | ```js 115 | // src/modules/module-b/modules/module-c/ModuleC.js 116 | import ModuleA from 'modules/module-a' 117 | ``` 118 | 119 | _`module-c` can import `module-d` because it is his brother_ 120 | 121 | ```js 122 | // modules/module-b/modules/module-c/ModuleC.js 123 | import ModuleD from '../module-d' 124 | ``` 125 | 126 | _`module-e` can import `module-d` because it is his uncle_ 127 | 128 | ```js 129 | // modules/module-b/modules/module-c/modules/module-e/ModuleE 130 | import ModuleD from 'modules/module-b/modules/module-d' 131 | ``` 132 | 133 | ### Error messages 134 | 135 | This rule provides information about the parent element of the imported one in case it is private, e.g. `Dependency is private of element of type 'modules' with elementName 'module-b'` 136 | 137 | You can also configure a custom error message for changing this default behaviour, or even custom error messages only for a specific rule option. Read ["error messages"](../../README.md#error-messages) in the main docs for further info about how to configure messages. 138 | 139 | ## Further reading 140 | 141 | Read [how to configure the `boundaries/elements` setting](../../README.md#global-settings) to assign an element type to each project's file. 142 | -------------------------------------------------------------------------------- /docs/rules/no-unknown-files.md: -------------------------------------------------------------------------------- 1 | # boundaries/no-unknown-files 2 | 3 | > Prevent creating files not recognized as any of the element types 4 | 5 | ## Rule details 6 | 7 | It checks local files paths. If the file is not recognized as part of any element defined in settings, it will be notified as an error. 8 | 9 | ### Options 10 | 11 | ``` 12 | "boundaries/no-unknown-files": [] 13 | ``` 14 | 15 | * `enabled`: for enabling the rule. 0=off, 1=warn, 2=error. 16 | 17 | ##### Options example 18 | 19 | ```jsonc 20 | { 21 | "rules": { 22 | "boundaries/no-unknown-files": [2] 23 | } 24 | } 25 | ``` 26 | 27 | ### Settings 28 | 29 | Examples in the next sections are based on the previous options example and these files and settings. 30 | 31 | ```txt 32 | src/ 33 | ├── helpers/ 34 | │ ├── data/ 35 | │ │ ├── sort.js 36 | │ │ └── parse.js 37 | │ └── permissions/ 38 | │ └── roles.js 39 | │ 40 | ├── foo.js 41 | └── index.js 42 | ``` 43 | 44 | ```jsonc 45 | { 46 | "settings": { 47 | "boundaries/ignore": ["src/index.js"], 48 | "boundaries/elements": [ 49 | { 50 | "type": "helpers", 51 | "pattern": "helpers/*/*.js", 52 | "mode": "file" 53 | } 54 | ] 55 | } 56 | } 57 | ``` 58 | 59 | ### Examples of **incorrect** files for this rule: 60 | 61 | _`foo.js` file is not recognized, so it is not allowed_ 62 | 63 | ```js 64 | // src/foo.js 65 | ``` 66 | 67 | ### Examples of **correct** files for this rule: 68 | 69 | _Helper files are allowed_ 70 | 71 | ```js 72 | // src/helpers/data/sort.js 73 | ``` 74 | 75 | _`index.js` file is not recognized, but it is ignored in settings_ 76 | 77 | ```js 78 | // src/index.js 79 | ``` 80 | 81 | ## Further reading 82 | 83 | * Read [how to configure the `boundaries/elements` setting](../../README.md#global-settings) to assign an element type to each project's file. 84 | -------------------------------------------------------------------------------- /docs/rules/no-unknown.md: -------------------------------------------------------------------------------- 1 | # boundaries/no-unknown 2 | 3 | > Prevent importing unknown elements from the known ones 4 | 5 | ## Rule details 6 | 7 | It checks `import` statements to local files. If the imported file is not recognized as any of the element types from settings, the `import` will be notified as an error. 8 | 9 | ### Options 10 | 11 | ``` 12 | "boundaries/no-unknown": [] 13 | ``` 14 | 15 | * `enabled`: for enabling the rule. 0=off, 1=warn, 2=error. 16 | 17 | ##### Options example 18 | 19 | ```jsonc 20 | { 21 | "rules": { 22 | "boundaries/no-unknown": [2] 23 | } 24 | } 25 | ``` 26 | ### Settings 27 | 28 | Examples in the next sections are based on the previous options example and these files and settings. 29 | 30 | ```txt 31 | src/ 32 | ├── components/ 33 | │ └─ atoms/ 34 | │ ├── atom-a/ 35 | │ │ ├── index.js 36 | │ │ └── AtomA.js 37 | │ └── atom-b/ 38 | │ ├── index.js 39 | │ └── AtomB.js 40 | ├── helpers/ 41 | │ ├── data/ 42 | │ │ ├── sort.js 43 | │ │ └── parse.js 44 | │ └── permissions/ 45 | │ └── roles.js 46 | │ 47 | ├── foo.js 48 | └── index.js 49 | ``` 50 | 51 | ```jsonc 52 | { 53 | "settings": { 54 | "boundaries/elements": [ 55 | { 56 | "type": "helpers", 57 | "pattern": "helpers/*/*.js", 58 | "mode": "file", 59 | "capture": ["category", "elementName"] 60 | }, 61 | { 62 | "type": "components", 63 | "pattern": "components/*/*", 64 | "mode": "folder", 65 | "capture": ["family", "elementName"] 66 | } 67 | ] 68 | } 69 | } 70 | ``` 71 | 72 | ### Examples of **incorrect** files for this rule: 73 | 74 | _Helpers can't import `foo.js` file because it is unknown_ 75 | 76 | ```js 77 | // src/helpers/data/parse.js 78 | import foo from '../../foo' 79 | ``` 80 | 81 | _Components can't import `index.js` file because it is unknown_ 82 | 83 | ```js 84 | // src/components/atoms/atom-a/AtomA.js 85 | import index from '../../../index' 86 | ``` 87 | 88 | ### Examples of **correct** files for this rule: 89 | 90 | _Components can import helpers_ 91 | 92 | ```js 93 | // src/components/atoms/atom-a/AtomA.js 94 | import index from '../../../helpers/data/parse' 95 | ``` 96 | 97 | _`index.js` file can import `foo.js` file because both are unknown_ 98 | 99 | ```js 100 | // src/index.js 101 | import foo from './foo' 102 | ``` 103 | 104 | ## Further reading 105 | 106 | * Read [how to configure the `boundaries/elements` setting](../../README.md#global-settings) to assign an element type to each project's file. 107 | 108 | -------------------------------------------------------------------------------- /eslint-local-rules.js: -------------------------------------------------------------------------------- 1 | const eslintPluginBoundaries = require("./src/index.js"); 2 | 3 | module.exports = Object.keys(eslintPluginBoundaries.rules).reduce((rules, ruleName) => { 4 | return { 5 | ...rules, 6 | [`boundaries/${ruleName}`]: eslintPluginBoundaries.rules[ruleName], 7 | }; 8 | }, {}); 9 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import prettier from "eslint-plugin-prettier"; 2 | import localRules from "eslint-plugin-local-rules"; 3 | import globals from "globals"; 4 | import path from "node:path"; 5 | import { fileURLToPath } from "node:url"; 6 | import js from "@eslint/js"; 7 | import { FlatCompat } from "@eslint/eslintrc"; 8 | 9 | const _filename = fileURLToPath(import.meta.url); 10 | const _dirname = path.dirname(_filename); 11 | const compat = new FlatCompat({ 12 | baseDirectory: _dirname, 13 | recommendedConfig: js.configs.recommended, 14 | allConfig: js.configs.all, 15 | }); 16 | 17 | export default [ 18 | ...compat.extends("prettier"), 19 | { 20 | plugins: { 21 | prettier, 22 | "local-rules": localRules, 23 | }, 24 | 25 | languageOptions: { 26 | globals: { 27 | ...globals.node, 28 | }, 29 | 30 | ecmaVersion: 2022, 31 | sourceType: "commonjs", 32 | }, 33 | 34 | rules: { 35 | "prettier/prettier": [ 36 | "error", 37 | { 38 | printWidth: 99, 39 | parser: "flow", 40 | }, 41 | ], 42 | 43 | "no-shadow": [ 44 | 2, 45 | { 46 | builtinGlobals: true, 47 | hoist: "all", 48 | }, 49 | ], 50 | 51 | "no-undef": "error", 52 | 53 | "no-unused-vars": [ 54 | "error", 55 | { 56 | vars: "all", 57 | args: "after-used", 58 | ignoreRestSiblings: false, 59 | }, 60 | ], 61 | }, 62 | }, 63 | { 64 | files: ["**/*.mjs"], 65 | languageOptions: { 66 | ecmaVersion: 2022, 67 | sourceType: "module", 68 | }, 69 | }, 70 | { 71 | files: ["src/**/*.js"], 72 | 73 | settings: { 74 | "boundaries/dependency-nodes": ["require", "import", "dynamic-import", "export"], 75 | 76 | "boundaries/elements": [ 77 | { 78 | type: "config", 79 | mode: "file", 80 | pattern: ["src/configs/*.js", "(package.json)"], 81 | capture: ["name"], 82 | }, 83 | { 84 | type: "constants", 85 | mode: "file", 86 | pattern: "src/constants/*.js", 87 | capture: ["name"], 88 | }, 89 | { 90 | type: "core", 91 | mode: "file", 92 | pattern: "src/core/*.js", 93 | capture: ["name"], 94 | }, 95 | { 96 | type: "helper", 97 | mode: "file", 98 | pattern: "src/helpers/*.js", 99 | capture: ["name"], 100 | }, 101 | { 102 | type: "rule", 103 | mode: "file", 104 | pattern: "src/rules/*.js", 105 | capture: ["name"], 106 | }, 107 | { 108 | type: "rule-factory", 109 | mode: "file", 110 | pattern: "src/rules-factories/*.js", 111 | capture: ["name"], 112 | }, 113 | { 114 | type: "plugin", 115 | mode: "full", 116 | pattern: ["src/index.js"], 117 | }, 118 | ], 119 | }, 120 | 121 | rules: { 122 | "local-rules/boundaries/element-types": [ 123 | 2, 124 | { 125 | default: "disallow", 126 | 127 | rules: [ 128 | { 129 | from: "plugin", 130 | allow: ["constants", "config", "rule"], 131 | }, 132 | { 133 | from: "config", 134 | allow: ["constants", "config"], 135 | }, 136 | { 137 | from: "constants", 138 | allow: ["constants"], 139 | }, 140 | { 141 | from: "core", 142 | allow: ["constants", "helper", "core"], 143 | }, 144 | { 145 | from: "helper", 146 | allow: ["constants", "helper"], 147 | }, 148 | { 149 | from: "rule", 150 | allow: ["constants", "helper", "core", "rule-factory"], 151 | }, 152 | { 153 | from: "rule-factory", 154 | allow: ["constants", "helper", "core"], 155 | }, 156 | ], 157 | }, 158 | ], 159 | 160 | "local-rules/boundaries/no-unknown": [2], 161 | "local-rules/boundaries/no-unknown-files": [2], 162 | }, 163 | }, 164 | { 165 | files: ["test/src/**/*.js"], 166 | 167 | plugins: { 168 | prettier, 169 | }, 170 | 171 | languageOptions: { 172 | globals: { 173 | ...globals.node, 174 | describe: "readonly", 175 | it: "readonly", 176 | expect: "readonly", 177 | }, 178 | 179 | ecmaVersion: 2022, 180 | sourceType: "commonjs", 181 | }, 182 | 183 | rules: { 184 | "prettier/prettier": [ 185 | "error", 186 | { 187 | printWidth: 99, 188 | parser: "flow", 189 | }, 190 | ], 191 | 192 | "no-shadow": [ 193 | 2, 194 | { 195 | builtinGlobals: true, 196 | hoist: "all", 197 | }, 198 | ], 199 | 200 | "no-undef": "error", 201 | 202 | "no-unused-vars": [ 203 | "error", 204 | { 205 | vars: "all", 206 | args: "after-used", 207 | ignoreRestSiblings: false, 208 | }, 209 | ], 210 | }, 211 | }, 212 | ]; 213 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require("./src"); 2 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | // For a detailed explanation regarding each configuration property, visit: 2 | // https://jestjs.io/docs/en/configuration.html 3 | 4 | module.exports = { 5 | // Automatically clear mock calls and instances between every test 6 | clearMocks: true, 7 | 8 | // Indicates whether the coverage information should be collected while executing the test 9 | collectCoverage: true, 10 | 11 | // An array of glob patterns indicating a set of files for which coverage information should be collected 12 | collectCoverageFrom: ["src/**"], 13 | 14 | // The directory where Jest should output its coverage files 15 | coverageDirectory: "coverage", 16 | 17 | // An object that configures minimum threshold enforcement for coverage results 18 | coverageThreshold: { 19 | global: { 20 | branches: 100, 21 | functions: 100, 22 | lines: 100, 23 | statements: 100, 24 | }, 25 | // Decrease coverage due to cache branches 26 | "./src/core/elementsInfo.js": { 27 | branches: 96, 28 | statements: 97, 29 | }, 30 | }, 31 | 32 | // The test environment that will be used for testing 33 | testEnvironment: "node", 34 | 35 | // The glob patterns Jest uses to detect test files 36 | testMatch: ["/test/**/*.spec.js"], 37 | }; 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-plugin-boundaries", 3 | "version": "5.0.1", 4 | "description": "Eslint plugin checking architecture boundaries between elements", 5 | "keywords": [ 6 | "eslint", 7 | "plugin", 8 | "architecture", 9 | "boundaries", 10 | "dependencies", 11 | "elements", 12 | "hierarchy", 13 | "import" 14 | ], 15 | "author": "Javier Brea", 16 | "license": "MIT", 17 | "repository": "https://github.com/javierbrea/eslint-plugin-boundaries", 18 | "files": [ 19 | "src", 20 | "resolver-legacy-alias" 21 | ], 22 | "main": "index.js", 23 | "scripts": { 24 | "eslint": "eslint", 25 | "lint": "eslint .", 26 | "lint-staged": "lint-staged", 27 | "test": "jest", 28 | "test:unit": "cross-env ESLINT_PLUGIN_BOUNDARIES_DEBUG=1 npm run test", 29 | "prepare": "is-ci || husky install" 30 | }, 31 | "peerDependencies": { 32 | "eslint": ">=6.0.0" 33 | }, 34 | "dependencies": { 35 | "chalk": "4.1.2", 36 | "eslint-import-resolver-node": "0.3.9", 37 | "eslint-module-utils": "2.12.0", 38 | "micromatch": "4.0.8" 39 | }, 40 | "devDependencies": { 41 | "@typescript-eslint/eslint-plugin": "8.13.0", 42 | "@typescript-eslint/parser": "8.13.0", 43 | "cross-env": "7.0.3", 44 | "eslint": "9.14.0", 45 | "eslint-config-prettier": "9.1.0", 46 | "eslint-plugin-local-rules": "3.0.2", 47 | "eslint-plugin-prettier": "5.2.1", 48 | "husky": "9.1.6", 49 | "is-ci": "3.0.1", 50 | "jest": "29.7.0", 51 | "lint-staged": "15.2.10", 52 | "prettier": "3.3.3" 53 | }, 54 | "lint-staged": { 55 | "**/*.js": "eslint", 56 | "**/*.ts": "eslint", 57 | "**/*.mjs": "eslint" 58 | }, 59 | "engines": { 60 | "node": ">=18.18" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "github>javierbrea/renovate-config" 4 | ], 5 | "packageRules": [ 6 | { 7 | "matchFileNames": [ 8 | "package.json" 9 | ], 10 | "matchPackageNames": [ 11 | "chalk" 12 | ], 13 | "allowedVersions": "<5.0.0" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /resolver-legacy-alias/index.js: -------------------------------------------------------------------------------- 1 | const resolve = require("resolve"); 2 | 3 | const getUsedAlias = (relativeFilePath, config) => { 4 | return Object.keys(config).find((alias) => relativeFilePath.indexOf(alias) === 0); 5 | }; 6 | 7 | const replaceAliases = (filePath, config) => { 8 | const usedAlias = getUsedAlias(filePath, config); 9 | if (usedAlias) { 10 | return filePath.replace(usedAlias, config[usedAlias]); 11 | } 12 | return filePath; 13 | }; 14 | 15 | module.exports = { 16 | interfaceVersion: 2, 17 | resolve: function (source, _file, config) { 18 | if (resolve.isCore(source)) return { found: true, path: null }; 19 | try { 20 | return { 21 | found: true, 22 | path: resolve.sync(replaceAliases(source, config), { 23 | basedir: process.cwd(), 24 | }), 25 | }; 26 | } catch { 27 | return { found: false }; 28 | } 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.organization=javierbrea 2 | sonar.projectKey=javierbrea_eslint-plugin-boundaries 3 | sonar.projectVersion=5.0.1 4 | 5 | sonar.javascript.file.suffixes=.js 6 | sonar.sourceEncoding=UTF-8 7 | sonar.exclusions=node_modules/** 8 | sonar.cpd.exclusions=test/**/* 9 | sonar.coverage.exclusions=test/**/*,index.js,stryker.conf.js,jest.config.js,resolver-legacy-alias/**/*,eslint-local-rules.js 10 | sonar.javascript.lcov.reportPaths=coverage/lcov.info 11 | sonar.host.url=https://sonarcloud.io 12 | -------------------------------------------------------------------------------- /src/configs/recommended.js: -------------------------------------------------------------------------------- 1 | const { 2 | ELEMENTS, 3 | // rules 4 | RULE_ELEMENT_TYPES, 5 | RULE_ENTRY_POINT, 6 | RULE_EXTERNAL, 7 | RULE_NO_IGNORED, 8 | RULE_NO_PRIVATE, 9 | RULE_NO_UNKNOWN_FILES, 10 | RULE_NO_UNKNOWN, 11 | } = require("../constants/settings"); 12 | 13 | module.exports = { 14 | rules: { 15 | [RULE_ELEMENT_TYPES]: [2], 16 | [RULE_ENTRY_POINT]: [2], 17 | [RULE_EXTERNAL]: [2], 18 | [RULE_NO_IGNORED]: 0, 19 | [RULE_NO_PRIVATE]: [ 20 | 2, 21 | { 22 | allowUncles: true, 23 | }, 24 | ], 25 | [RULE_NO_UNKNOWN_FILES]: 0, 26 | [RULE_NO_UNKNOWN]: 0, 27 | }, 28 | settings: { 29 | [ELEMENTS]: [], 30 | }, 31 | }; 32 | -------------------------------------------------------------------------------- /src/configs/strict.js: -------------------------------------------------------------------------------- 1 | const { 2 | RULE_NO_IGNORED, 3 | RULE_NO_UNKNOWN_FILES, 4 | RULE_NO_UNKNOWN, 5 | } = require("../constants/settings"); 6 | 7 | const recommended = require("./recommended"); 8 | 9 | module.exports = { 10 | ...recommended, 11 | rules: { 12 | ...recommended.rules, 13 | [RULE_NO_IGNORED]: 2, 14 | [RULE_NO_UNKNOWN_FILES]: 2, 15 | [RULE_NO_UNKNOWN]: 2, 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /src/constants/plugin.js: -------------------------------------------------------------------------------- 1 | const PLUGIN_NAME = "boundaries"; 2 | const PLUGIN_ENV_VARS_PREFIX = "ESLINT_PLUGIN_BOUNDARIES"; 3 | 4 | module.exports = { 5 | PLUGIN_NAME, 6 | PLUGIN_ENV_VARS_PREFIX, 7 | }; 8 | -------------------------------------------------------------------------------- /src/constants/rules.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ELEMENT_TYPES: "element-types", 3 | ENTRY_POINT: "entry-point", 4 | EXTERNAL: "external", 5 | NO_IGNORED: "no-ignored", 6 | NO_PRIVATE: "no-private", 7 | NO_UNKNOWN_FILES: "no-unknown-files", 8 | NO_UNKNOWN: "no-unknown", 9 | }; 10 | -------------------------------------------------------------------------------- /src/constants/settings.js: -------------------------------------------------------------------------------- 1 | const { PLUGIN_NAME, PLUGIN_ENV_VARS_PREFIX } = require("./plugin"); 2 | 3 | const { 4 | ELEMENT_TYPES, 5 | EXTERNAL, 6 | ENTRY_POINT, 7 | NO_IGNORED, 8 | NO_UNKNOWN, 9 | NO_PRIVATE, 10 | NO_UNKNOWN_FILES, 11 | } = require("./rules"); 12 | 13 | module.exports = { 14 | // settings 15 | ELEMENTS: `${PLUGIN_NAME}/elements`, 16 | IGNORE: `${PLUGIN_NAME}/ignore`, 17 | INCLUDE: `${PLUGIN_NAME}/include`, 18 | ROOT_PATH: `${PLUGIN_NAME}/root-path`, 19 | DEPENDENCY_NODES: `${PLUGIN_NAME}/dependency-nodes`, 20 | ADDITIONAL_DEPENDENCY_NODES: `${PLUGIN_NAME}/additional-dependency-nodes`, 21 | 22 | // env vars 23 | DEBUG: `${PLUGIN_ENV_VARS_PREFIX}_DEBUG`, 24 | ENV_ROOT_PATH: `${PLUGIN_ENV_VARS_PREFIX}_ROOT_PATH`, 25 | 26 | // rules 27 | RULE_ELEMENT_TYPES: `${PLUGIN_NAME}/${ELEMENT_TYPES}`, 28 | RULE_ENTRY_POINT: `${PLUGIN_NAME}/${ENTRY_POINT}`, 29 | RULE_EXTERNAL: `${PLUGIN_NAME}/${EXTERNAL}`, 30 | RULE_NO_IGNORED: `${PLUGIN_NAME}/${NO_IGNORED}`, 31 | RULE_NO_PRIVATE: `${PLUGIN_NAME}/${NO_PRIVATE}`, 32 | RULE_NO_UNKNOWN_FILES: `${PLUGIN_NAME}/${NO_UNKNOWN_FILES}`, 33 | RULE_NO_UNKNOWN: `${PLUGIN_NAME}/${NO_UNKNOWN}`, 34 | 35 | // deprecated settings 36 | TYPES: `${PLUGIN_NAME}/types`, 37 | ALIAS: `${PLUGIN_NAME}/alias`, 38 | 39 | // elements settings properties, 40 | VALID_MODES: ["folder", "file", "full"], 41 | 42 | VALID_DEPENDENCY_NODE_KINDS: ["value", "type"], 43 | DEFAULT_DEPENDENCY_NODES: { 44 | require: [ 45 | // Note: detects "require('source')" 46 | { 47 | selector: "CallExpression[callee.name=require] > Literal", 48 | kind: "value", 49 | }, 50 | ], 51 | import: [ 52 | // Note: detects "import x from 'source'" 53 | { selector: "ImportDeclaration:not([importKind=type]) > Literal", kind: "value" }, 54 | // Note: detects "import type x from 'source'" 55 | { selector: "ImportDeclaration[importKind=type] > Literal", kind: "type" }, 56 | ], 57 | "dynamic-import": [ 58 | // Note: detects "import('source')" 59 | { selector: "ImportExpression > Literal", kind: "value" }, 60 | ], 61 | export: [ 62 | // Note: detects "export * from 'source'"; 63 | { selector: "ExportAllDeclaration:not([exportKind=type]) > Literal", kind: "value" }, 64 | // Note: detects "export type * from 'source'"; 65 | { selector: "ExportAllDeclaration[exportKind=type] > Literal", kind: "type" }, 66 | // Note: detects "export { x } from 'source'"; 67 | { selector: "ExportNamedDeclaration:not([exportKind=type]) > Literal", kind: "value" }, 68 | // Note: detects "export type { x } from 'source'"; 69 | { selector: "ExportNamedDeclaration[exportKind=type] > Literal", kind: "type" }, 70 | ], 71 | }, 72 | }; 73 | -------------------------------------------------------------------------------- /src/core/cache.js: -------------------------------------------------------------------------------- 1 | class Cache { 2 | constructor(name, settings) { 3 | this._cache = {}; 4 | this._name = name; 5 | this._settings = settings; 6 | } 7 | 8 | save(key, value) { 9 | this._cache[key] = value; 10 | } 11 | 12 | load(key) { 13 | if (this._cache[key]) { 14 | return this._cache[key]; 15 | } 16 | 17 | return null; 18 | } 19 | } 20 | 21 | class CachesManager { 22 | constructor(name) { 23 | this._name = name; 24 | this._caches = []; 25 | } 26 | 27 | findCacheForSettings(settings) { 28 | let cache = this._caches.find((cacheCandidate) => { 29 | return cacheCandidate._settings === settings; 30 | }); 31 | if (!cache) { 32 | cache = new Cache(this._name, settings); 33 | this._caches.push(cache); 34 | } 35 | return cache; 36 | } 37 | 38 | save(key, value, settings) { 39 | const cache = this.findCacheForSettings(settings); 40 | cache.save(key, value); 41 | } 42 | 43 | load(key, settings) { 44 | const cache = this.findCacheForSettings(settings); 45 | return cache.load(key); 46 | } 47 | } 48 | 49 | const filesCache = new CachesManager("file"); 50 | const importsCache = new CachesManager("import"); 51 | const elementsCache = new CachesManager("element"); 52 | 53 | module.exports = { 54 | filesCache, 55 | importsCache, 56 | elementsCache, 57 | }; 58 | -------------------------------------------------------------------------------- /src/core/dependencyInfo.js: -------------------------------------------------------------------------------- 1 | const { fileInfo, importInfo } = require("./elementsInfo"); 2 | 3 | function getParent(elementInfo) { 4 | return elementInfo.parents?.[0]?.elementPath; 5 | } 6 | 7 | function getCommonAncestor(elementInfoA, elementInfoB) { 8 | const commonAncestor = elementInfoA.parents.find((elementParentA) => { 9 | return !!elementInfoB.parents.find((elementParentB) => { 10 | return elementParentA.elementPath === elementParentB.elementPath; 11 | }); 12 | }); 13 | return commonAncestor?.elementPath; 14 | } 15 | 16 | function isUncle(elementA, elementB) { 17 | const commonAncestor = getCommonAncestor(elementA, elementB); 18 | return commonAncestor && commonAncestor === getParent(elementA); 19 | } 20 | 21 | function isBrother(elementA, elementB) { 22 | const parentA = getParent(elementA); 23 | const parentB = getParent(elementB); 24 | return parentA && parentB && parentA === parentB; 25 | } 26 | 27 | function isDescendant(elementA, elementB) { 28 | return !!elementA.parents.find((parent) => parent.elementPath === elementB.elementPath); 29 | } 30 | 31 | function isChild(elementA, elementB) { 32 | return getParent(elementA) == elementB.elementPath; 33 | } 34 | 35 | function isInternal(elementA, elementB) { 36 | return elementA.elementPath === elementB.elementPath; 37 | } 38 | 39 | function dependencyRelationship(dependency, element) { 40 | if (!dependency.isLocal || dependency.isIgnored || !element.type || !dependency.type) { 41 | return null; 42 | } 43 | if (isInternal(dependency, element)) { 44 | return "internal"; 45 | } 46 | if (isChild(dependency, element)) { 47 | return "child"; 48 | } 49 | if (isDescendant(dependency, element)) { 50 | return "descendant"; 51 | } 52 | if (isBrother(dependency, element)) { 53 | return "brother"; 54 | } 55 | if (isChild(element, dependency)) { 56 | return "parent"; 57 | } 58 | if (isUncle(dependency, element)) { 59 | return "uncle"; 60 | } 61 | if (isDescendant(element, dependency)) { 62 | return "ancestor"; 63 | } 64 | return null; 65 | } 66 | 67 | function dependencyInfo(source, importKind, context) { 68 | const elementInfo = fileInfo(context); 69 | const dependency = importInfo(source, context); 70 | 71 | return { 72 | ...dependency, 73 | importKind: importKind || "value", 74 | relationship: dependencyRelationship(dependency, elementInfo), 75 | isInternal: isInternal(dependency, elementInfo), 76 | }; 77 | } 78 | 79 | module.exports = { 80 | dependencyInfo, 81 | }; 82 | -------------------------------------------------------------------------------- /src/helpers/debug.js: -------------------------------------------------------------------------------- 1 | const chalk = require("chalk"); 2 | 3 | const { PLUGIN_NAME } = require("../constants/plugin"); 4 | const { isDebugModeEnabled } = require("./settings"); 5 | 6 | const warns = []; 7 | const debuggedFiles = []; 8 | 9 | function trace(message, color) { 10 | console.log(chalk[color](`[${PLUGIN_NAME}]: ${message}`)); 11 | } 12 | 13 | function warn(message) { 14 | trace(message, "yellow"); 15 | } 16 | 17 | function success(message) { 18 | trace(message, "green"); 19 | } 20 | 21 | function warnOnce(message) { 22 | if (!warns.includes(message)) { 23 | warns.push(message); 24 | warn(message); 25 | } 26 | } 27 | 28 | function debugFileInfo(fileInfo) { 29 | const fileInfoKey = fileInfo.path || fileInfo.source; 30 | if (isDebugModeEnabled() && !debuggedFiles.includes(fileInfoKey)) { 31 | debuggedFiles.push(fileInfoKey); 32 | if (fileInfo.type) { 33 | success(`'${fileInfoKey}' is of type '${fileInfo.type}'`); 34 | } else { 35 | warn(`'${fileInfoKey}' is of unknown type`); 36 | } 37 | console.log(JSON.stringify(fileInfo, null, 2)); 38 | } 39 | } 40 | 41 | module.exports = { 42 | success, 43 | debugFileInfo, 44 | warnOnce, 45 | }; 46 | -------------------------------------------------------------------------------- /src/helpers/messages.js: -------------------------------------------------------------------------------- 1 | const { isString, isArray, replaceObjectValuesInTemplates } = require("./utils"); 2 | const { micromatchPatternReplacingObjectsValues } = require("./rules"); 3 | 4 | function quote(str) { 5 | return `'${str}'`; 6 | } 7 | 8 | function typeMessage(elementMatcher) { 9 | return `elements of type ${quote(elementMatcher)}`; 10 | } 11 | 12 | function propertiesConcater(properties, index) { 13 | if (properties.length > 1 && index === properties.length - 1) { 14 | return " and"; 15 | } 16 | if (index === 0) { 17 | return " with"; 18 | } 19 | return ","; 20 | } 21 | 22 | function micromatchPatternMessage(micromatchPatterns, elementCapturedValues) { 23 | const micromatchPatternsWithValues = micromatchPatternReplacingObjectsValues( 24 | micromatchPatterns, 25 | { from: elementCapturedValues }, 26 | ); 27 | if (isArray(micromatchPatternsWithValues)) { 28 | if (micromatchPatternsWithValues.length === 1) { 29 | return quote(micromatchPatternsWithValues[0]); 30 | } 31 | return micromatchPatternsWithValues.reduce((message, micromatchPattern, index) => { 32 | if (index === 0) { 33 | return quote(micromatchPattern); 34 | } 35 | if (index === micromatchPatternsWithValues.length - 1) { 36 | return `${message} or ${quote(micromatchPattern)}`; 37 | } 38 | return `${message}, ${quote(micromatchPattern)}`; 39 | }, ""); 40 | } 41 | return quote(micromatchPatternsWithValues); 42 | } 43 | 44 | function capturedValuesMatcherMessage(capturedValuesPattern, elementCapturedValues) { 45 | const capturedValuesPatternKeys = Object.keys(capturedValuesPattern); 46 | return capturedValuesPatternKeys 47 | .map((key) => { 48 | return [key, capturedValuesPattern[key]]; 49 | }) 50 | .reduce((message, propertyNameAndMatcher, index) => { 51 | return `${message}${propertiesConcater(capturedValuesPatternKeys, index)} ${ 52 | propertyNameAndMatcher[0] 53 | } ${micromatchPatternMessage(propertyNameAndMatcher[1], elementCapturedValues)}`; 54 | }, ""); 55 | } 56 | 57 | function elementMatcherMessage(elementMatcher, elementCapturedValues) { 58 | if (isString(elementMatcher)) { 59 | return typeMessage(elementMatcher); 60 | } 61 | return `${typeMessage(elementMatcher[0])}${capturedValuesMatcherMessage( 62 | elementMatcher[1], 63 | elementCapturedValues, 64 | )}`; 65 | } 66 | 67 | function ruleElementMessage(elementPatterns, elementCapturedValues) { 68 | if (isArray(elementPatterns)) { 69 | if (elementPatterns.length === 1) { 70 | return elementMatcherMessage(elementPatterns[0], elementCapturedValues); 71 | } 72 | return elementPatterns.reduce((message, elementPattern, index) => { 73 | if (index === 0) { 74 | return elementMatcherMessage(elementPattern, elementCapturedValues); 75 | } 76 | return `${message}, or ${elementMatcherMessage(elementPattern, elementCapturedValues)}`; 77 | }, ""); 78 | } 79 | return elementMatcherMessage(elementPatterns, elementCapturedValues); 80 | } 81 | 82 | function elementPropertiesToReplaceInTemplate(element) { 83 | return { 84 | ...element.capturedValues, 85 | type: element.type, 86 | internalPath: element.internalPath, 87 | source: element.source, 88 | importKind: element.importKind, 89 | }; 90 | } 91 | 92 | function customErrorMessage(message, file, dependency, report = {}) { 93 | let replacedMessage = replaceObjectValuesInTemplates( 94 | replaceObjectValuesInTemplates(message, elementPropertiesToReplaceInTemplate(file), "file"), 95 | elementPropertiesToReplaceInTemplate(dependency), 96 | "dependency", 97 | ); 98 | replacedMessage = replaceObjectValuesInTemplates( 99 | replaceObjectValuesInTemplates( 100 | replacedMessage, 101 | elementPropertiesToReplaceInTemplate(file), 102 | "from", 103 | ), 104 | elementPropertiesToReplaceInTemplate(dependency), 105 | "target", 106 | ); 107 | if (file.parents[0]) { 108 | replacedMessage = replaceObjectValuesInTemplates( 109 | replacedMessage, 110 | elementPropertiesToReplaceInTemplate(file.parents[0]), 111 | "file.parent", 112 | ); 113 | replacedMessage = replaceObjectValuesInTemplates( 114 | replacedMessage, 115 | elementPropertiesToReplaceInTemplate(file.parents[0]), 116 | "from.parent", 117 | ); 118 | } 119 | if (dependency.parents[0]) { 120 | replacedMessage = replaceObjectValuesInTemplates( 121 | replacedMessage, 122 | elementPropertiesToReplaceInTemplate(dependency.parents[0]), 123 | "dependency.parent", 124 | ); 125 | replacedMessage = replaceObjectValuesInTemplates( 126 | replacedMessage, 127 | elementPropertiesToReplaceInTemplate(dependency.parents[0]), 128 | "target.parent", 129 | ); 130 | } 131 | return replaceObjectValuesInTemplates(replacedMessage, report, "report"); 132 | } 133 | 134 | function elementCapturedValuesMessage(capturedValues) { 135 | if (!capturedValues) { 136 | return ""; 137 | } 138 | const capturedValuesKeys = Object.keys(capturedValues); 139 | return capturedValuesKeys 140 | .map((key) => { 141 | return [key, capturedValues[key]]; 142 | }) 143 | .reduce((message, propertyNameAndValue, index) => { 144 | return `${message}${propertiesConcater(capturedValuesKeys, index)} ${ 145 | propertyNameAndValue[0] 146 | } ${quote(propertyNameAndValue[1])}`; 147 | }, ""); 148 | } 149 | 150 | function elementMessage(elementInfo) { 151 | return `of type ${quote(elementInfo.type)}${elementCapturedValuesMessage( 152 | elementInfo.capturedValues, 153 | )}`; 154 | } 155 | 156 | function hasToPrintKindMessage(ruleImportKind, dependencyInfo) { 157 | return ruleImportKind && dependencyInfo.importKind; 158 | } 159 | 160 | function dependencyImportKindMessage(ruleImportKind, dependencyInfo) { 161 | if (hasToPrintKindMessage(ruleImportKind, dependencyInfo)) { 162 | return `kind ${quote(dependencyInfo.importKind)} from `; 163 | } 164 | return ""; 165 | } 166 | 167 | function dependencyUsageKindMessage( 168 | ruleImportKind, 169 | dependencyInfo, 170 | { suffix = " ", prefix = "" } = {}, 171 | ) { 172 | if (hasToPrintKindMessage(ruleImportKind, dependencyInfo)) { 173 | return `${prefix}${dependencyInfo.importKind}${suffix}`; 174 | } 175 | return ""; 176 | } 177 | 178 | module.exports = { 179 | quote, 180 | ruleElementMessage, 181 | customErrorMessage, 182 | elementMessage, 183 | dependencyImportKindMessage, 184 | dependencyUsageKindMessage, 185 | }; 186 | -------------------------------------------------------------------------------- /src/helpers/settings.js: -------------------------------------------------------------------------------- 1 | const { 2 | TYPES, 3 | ELEMENTS, 4 | VALID_MODES, 5 | ROOT_PATH, 6 | ENV_ROOT_PATH, 7 | DEBUG, 8 | } = require("../constants/settings"); 9 | const { isString } = require("./utils"); 10 | const { isAbsolute, resolve } = require("path"); 11 | 12 | function isLegacyType(type) { 13 | return isString(type); 14 | } 15 | 16 | // TODO, remove in next major version 17 | function transformLegacyTypes(typesFromSettings) { 18 | const types = typesFromSettings || []; 19 | return types.map((type) => { 20 | // backward compatibility with v1 21 | if (isLegacyType(type)) { 22 | return { 23 | type: type, 24 | match: VALID_MODES[0], 25 | pattern: `${type}/*`, 26 | capture: ["elementName"], 27 | }; 28 | } 29 | // default options 30 | return { 31 | match: VALID_MODES[0], 32 | ...type, 33 | }; 34 | }); 35 | } 36 | 37 | function getElements(settings) { 38 | return transformLegacyTypes(settings[ELEMENTS] || settings[TYPES]); 39 | } 40 | 41 | function getElementsTypeNames(settings) { 42 | return getElements(settings).map((element) => element.type); 43 | } 44 | 45 | function getRootPath(settings) { 46 | const rootPathUserSetting = process.env[ENV_ROOT_PATH] || settings[ROOT_PATH]; 47 | if (rootPathUserSetting) { 48 | return isAbsolute(rootPathUserSetting) 49 | ? rootPathUserSetting 50 | : resolve(process.cwd(), rootPathUserSetting); 51 | } 52 | return process.cwd(); 53 | } 54 | 55 | function isDebugModeEnabled() { 56 | return process.env[DEBUG]; 57 | } 58 | 59 | module.exports = { 60 | isLegacyType, 61 | getElements, 62 | getElementsTypeNames, 63 | isDebugModeEnabled, 64 | getRootPath, 65 | }; 66 | -------------------------------------------------------------------------------- /src/helpers/utils.js: -------------------------------------------------------------------------------- 1 | function isString(object) { 2 | return typeof object === "string"; 3 | } 4 | 5 | function isArray(object) { 6 | return Array.isArray(object); 7 | } 8 | 9 | function isObject(object) { 10 | return typeof object === "object" && object !== null && !isArray(object); 11 | } 12 | 13 | function getArrayOrNull(value) { 14 | return isArray(value) ? value : null; 15 | } 16 | 17 | function replaceObjectValueInTemplate(template, key, value, namespace) { 18 | const keyToReplace = namespace ? `${namespace}.${key}` : key; 19 | const regexp = new RegExp(`\\$\\{${keyToReplace}\\}`, "g"); 20 | return template.replace(regexp, value); 21 | } 22 | 23 | function replaceObjectValuesInTemplates(strings, object, namespace) { 24 | return Object.keys(object).reduce((result, objectKey) => { 25 | // If template is an array, replace key by value in all patterns 26 | if (isArray(result)) { 27 | return result.map((resultEntry) => { 28 | return replaceObjectValueInTemplate(resultEntry, objectKey, object[objectKey], namespace); 29 | }); 30 | } 31 | return replaceObjectValueInTemplate(result, objectKey, object[objectKey], namespace); 32 | }, strings); 33 | } 34 | 35 | module.exports = { 36 | isString, 37 | isArray, 38 | isObject, 39 | getArrayOrNull, 40 | replaceObjectValuesInTemplates, 41 | }; 42 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const packageJson = require("../package.json"); 2 | const rules = require("./constants/rules"); 3 | const recommendedConfig = require("./configs/recommended"); 4 | const strictConfig = require("./configs/strict"); 5 | 6 | const importRules = (ruleNames) => { 7 | return Object.keys(ruleNames).reduce((loadedRules, ruleKey) => { 8 | loadedRules[rules[ruleKey]] = require(`./rules/${rules[ruleKey]}`); 9 | return loadedRules; 10 | }, {}); 11 | }; 12 | 13 | //------------------------------------------------------------------------------ 14 | // Plugin Definition 15 | //------------------------------------------------------------------------------ 16 | 17 | // export all rules in lib/rules 18 | // export all configs 19 | 20 | module.exports = { 21 | meta: { 22 | name: packageJson.name, 23 | version: packageJson.version, 24 | }, 25 | rules: importRules(rules), 26 | configs: { 27 | recommended: recommendedConfig, 28 | strict: strictConfig, 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /src/rules-factories/dependency-rule.js: -------------------------------------------------------------------------------- 1 | const { 2 | DEPENDENCY_NODES, 3 | DEFAULT_DEPENDENCY_NODES, 4 | ADDITIONAL_DEPENDENCY_NODES, 5 | } = require("../constants/settings"); 6 | const { getArrayOrNull } = require("../helpers/utils"); 7 | const { fileInfo } = require("../core/elementsInfo"); 8 | const { dependencyInfo } = require("../core/dependencyInfo"); 9 | 10 | const { validateSettings, validateRules } = require("../helpers/validations"); 11 | 12 | const { meta } = require("../helpers/rules"); 13 | 14 | module.exports = function (ruleMeta, rule, ruleOptions = {}) { 15 | return { 16 | ...meta(ruleMeta), 17 | create: function (context) { 18 | const options = context.options[0]; 19 | validateSettings(context.settings); 20 | const file = fileInfo(context); 21 | if ((ruleOptions.validate !== false && !options) || file.isIgnored || !file.type) { 22 | return {}; 23 | } 24 | if (ruleOptions.validate !== false) { 25 | validateRules(context.settings, options.rules, ruleOptions.validateRules); 26 | } 27 | 28 | const dependencyNodesSetting = getArrayOrNull(context.settings[DEPENDENCY_NODES]); 29 | const additionalDependencyNodesSetting = getArrayOrNull( 30 | context.settings[ADDITIONAL_DEPENDENCY_NODES], 31 | ); 32 | const dependencyNodes = (dependencyNodesSetting || ["import"]) 33 | .map((dependencyNode) => DEFAULT_DEPENDENCY_NODES[dependencyNode]) 34 | .flat() 35 | .filter(Boolean); 36 | const additionalDependencyNodes = additionalDependencyNodesSetting || []; 37 | 38 | return [...dependencyNodes, ...additionalDependencyNodes].reduce( 39 | (visitors, { selector, kind }) => { 40 | visitors[selector] = (node) => { 41 | const dependency = dependencyInfo(node.value, kind, context); 42 | 43 | rule({ file, dependency, options, node, context }); 44 | }; 45 | 46 | return visitors; 47 | }, 48 | {}, 49 | ); 50 | }, 51 | }; 52 | }; 53 | -------------------------------------------------------------------------------- /src/rules/element-types.js: -------------------------------------------------------------------------------- 1 | const { RULE_ELEMENT_TYPES } = require("../constants/settings"); 2 | 3 | const dependencyRule = require("../rules-factories/dependency-rule"); 4 | 5 | const { rulesOptionsSchema } = require("../helpers/validations"); 6 | const { isMatchElementType, elementRulesAllowDependency } = require("../helpers/rules"); 7 | const { 8 | customErrorMessage, 9 | ruleElementMessage, 10 | elementMessage, 11 | dependencyImportKindMessage, 12 | } = require("../helpers/messages"); 13 | 14 | function elementRulesAllowDependencyType(element, dependency, options) { 15 | return elementRulesAllowDependency({ 16 | element, 17 | dependency, 18 | options, 19 | isMatch: isMatchElementType, 20 | }); 21 | } 22 | 23 | function errorMessage(ruleData, file, dependency) { 24 | const ruleReport = ruleData.ruleReport; 25 | if (ruleReport.message) { 26 | return customErrorMessage(ruleReport.message, file, dependency); 27 | } 28 | if (ruleReport.isDefault) { 29 | return `No rule allowing this dependency was found. File is ${elementMessage( 30 | file, 31 | )}. Dependency is ${elementMessage(dependency)}`; 32 | } 33 | return `Importing ${dependencyImportKindMessage( 34 | ruleReport.importKind, 35 | dependency, 36 | )}${ruleElementMessage( 37 | ruleReport.disallow, 38 | file.capturedValues, 39 | )} is not allowed in ${ruleElementMessage( 40 | ruleReport.element, 41 | file.capturedValues, 42 | )}. Disallowed in rule ${ruleReport.index + 1}`; 43 | } 44 | 45 | module.exports = dependencyRule( 46 | { 47 | ruleName: RULE_ELEMENT_TYPES, 48 | description: `Check allowed dependencies between element types`, 49 | schema: rulesOptionsSchema(), 50 | }, 51 | function ({ dependency, file, node, context, options }) { 52 | if (dependency.isLocal && !dependency.isIgnored && dependency.type && !dependency.isInternal) { 53 | const ruleData = elementRulesAllowDependencyType(file, dependency, options); 54 | if (!ruleData.result) { 55 | context.report({ 56 | message: errorMessage(ruleData, file, dependency), 57 | node: node, 58 | }); 59 | } 60 | } 61 | }, 62 | ); 63 | -------------------------------------------------------------------------------- /src/rules/entry-point.js: -------------------------------------------------------------------------------- 1 | const { RULE_ENTRY_POINT } = require("../constants/settings"); 2 | 3 | const dependencyRule = require("../rules-factories/dependency-rule"); 4 | 5 | const { rulesOptionsSchema } = require("../helpers/validations"); 6 | const { 7 | isMatchElementKey, 8 | elementRulesAllowDependency, 9 | isMatchImportKind, 10 | } = require("../helpers/rules"); 11 | const { 12 | customErrorMessage, 13 | ruleElementMessage, 14 | elementMessage, 15 | dependencyUsageKindMessage, 16 | } = require("../helpers/messages"); 17 | 18 | function isMatchElementInternalPath( 19 | elementInfo, 20 | matcher, 21 | options, 22 | elementsCapturedValues, 23 | importKind, 24 | ) { 25 | if (!isMatchImportKind(elementInfo, importKind)) { 26 | return { result: false }; 27 | } 28 | return isMatchElementKey(elementInfo, matcher, options, "internalPath", elementsCapturedValues); 29 | } 30 | 31 | function elementRulesAllowEntryPoint(element, dependency, options) { 32 | return elementRulesAllowDependency({ 33 | element, 34 | dependency, 35 | options, 36 | isMatch: isMatchElementInternalPath, 37 | rulesMainKey: "target", 38 | }); 39 | } 40 | 41 | function errorMessage(ruleData, file, dependency) { 42 | const ruleReport = ruleData.ruleReport; 43 | if (ruleReport.message) { 44 | return customErrorMessage(ruleReport.message, file, dependency); 45 | } 46 | if (ruleReport.isDefault) { 47 | return `No rule allows the entry point '${ 48 | dependency.internalPath 49 | }' in dependencies ${elementMessage(dependency)}`; 50 | } 51 | return `The entry point '${dependency.internalPath}' is not allowed in ${ruleElementMessage( 52 | ruleReport.element, 53 | dependency.capturedValues, 54 | )}${dependencyUsageKindMessage(ruleReport.importKind, dependency, { 55 | prefix: " when importing ", 56 | suffix: "", 57 | })}. Disallowed in rule ${ruleReport.index + 1}`; 58 | } 59 | 60 | module.exports = dependencyRule( 61 | { 62 | ruleName: RULE_ENTRY_POINT, 63 | description: `Check entry point used for each element type`, 64 | schema: rulesOptionsSchema({ 65 | rulesMainKey: "target", 66 | }), 67 | }, 68 | function ({ dependency, file, node, context, options }) { 69 | if (!dependency.isIgnored && dependency.type && !dependency.isInternal) { 70 | const ruleData = elementRulesAllowEntryPoint(file, dependency, options); 71 | if (!ruleData.result) { 72 | context.report({ 73 | message: errorMessage(ruleData, file, dependency), 74 | node: node, 75 | }); 76 | } 77 | } 78 | }, 79 | { 80 | validateRules: { onlyMainKey: true, mainKey: "target" }, 81 | }, 82 | ); 83 | -------------------------------------------------------------------------------- /src/rules/external.js: -------------------------------------------------------------------------------- 1 | const micromatch = require("micromatch"); 2 | 3 | const { RULE_EXTERNAL } = require("../constants/settings"); 4 | 5 | const dependencyRule = require("../rules-factories/dependency-rule"); 6 | 7 | const { rulesOptionsSchema } = require("../helpers/validations"); 8 | const { 9 | elementRulesAllowDependency, 10 | micromatchPatternReplacingObjectsValues, 11 | isMatchImportKind, 12 | } = require("../helpers/rules"); 13 | const { 14 | customErrorMessage, 15 | ruleElementMessage, 16 | elementMessage, 17 | dependencyUsageKindMessage, 18 | } = require("../helpers/messages"); 19 | const { isArray } = require("../helpers/utils"); 20 | 21 | function getSpecifiers(node) { 22 | if (node.parent.type === "ImportDeclaration") { 23 | return node.parent.specifiers 24 | .filter((specifier) => specifier.type === "ImportSpecifier" && specifier.imported.name) 25 | .map((specifier) => specifier.imported.name); 26 | } 27 | 28 | if (node.parent.type === "ExportNamedDeclaration") { 29 | return node.parent.specifiers 30 | .filter((specifier) => specifier.type === "ExportSpecifier" && specifier.exported.name) 31 | .map((specifier) => specifier.exported.name); 32 | } 33 | 34 | return []; 35 | } 36 | 37 | function specifiersMatch(specifiers, specifierOptions, elementsCapturedValues) { 38 | return specifierOptions.reduce((found, option) => { 39 | const matcherWithTemplateReplaced = micromatchPatternReplacingObjectsValues( 40 | option, 41 | elementsCapturedValues, 42 | ); 43 | if (micromatch.some(specifiers, matcherWithTemplateReplaced)) { 44 | found.push(option); 45 | } 46 | return found; 47 | }, []); 48 | } 49 | 50 | function pathMatch(path, pathOptions, elementsCapturedValues) { 51 | const pathMatchers = isArray(pathOptions) ? pathOptions : [pathOptions]; 52 | return pathMatchers.reduce((isMatch, option) => { 53 | if (isMatch) { 54 | return isMatch; 55 | } 56 | const matcherWithTemplateReplaced = micromatchPatternReplacingObjectsValues( 57 | option, 58 | elementsCapturedValues, 59 | ); 60 | if (micromatch.some(path, matcherWithTemplateReplaced)) { 61 | isMatch = true; 62 | } 63 | return isMatch; 64 | }, false); 65 | } 66 | 67 | function isMatchExternalDependency( 68 | dependency, 69 | matcher, 70 | options, 71 | elementsCapturedValues, 72 | importKind, 73 | ) { 74 | const matcherWithTemplatesReplaced = micromatchPatternReplacingObjectsValues( 75 | matcher, 76 | elementsCapturedValues, 77 | ); 78 | if (!isMatchImportKind(dependency, importKind)) { 79 | return { result: false }; 80 | } 81 | const isMatch = micromatch.isMatch(dependency.baseModule, matcherWithTemplatesReplaced); 82 | if (isMatch && options && Object.keys(options).length) { 83 | const isPathMatch = options.path 84 | ? pathMatch(dependency.path, options.path, elementsCapturedValues) 85 | : true; 86 | if (isPathMatch && options.specifiers) { 87 | const specifiersResult = specifiersMatch( 88 | dependency.specifiers, 89 | options.specifiers, 90 | elementsCapturedValues, 91 | ); 92 | return { 93 | result: specifiersResult.length > 0, 94 | report: { 95 | specifiers: specifiersResult, 96 | }, 97 | }; 98 | } 99 | return { 100 | result: isPathMatch, 101 | report: { 102 | path: dependency.path, 103 | }, 104 | }; 105 | } 106 | return { 107 | result: isMatch, 108 | }; 109 | } 110 | 111 | function elementRulesAllowExternalDependency(element, dependency, options) { 112 | return elementRulesAllowDependency({ 113 | element, 114 | dependency, 115 | options, 116 | isMatch: isMatchExternalDependency, 117 | }); 118 | } 119 | 120 | function getErrorReportMessage(report) { 121 | if (report.path) { 122 | return report.path; 123 | } 124 | return report.specifiers.join(", "); 125 | } 126 | 127 | function errorMessage(ruleData, file, dependency) { 128 | const ruleReport = ruleData.ruleReport; 129 | if (ruleReport.message) { 130 | return customErrorMessage(ruleReport.message, file, dependency, { 131 | specifiers: ruleData.report?.specifiers?.join(", "), 132 | path: ruleData.report?.path, 133 | }); 134 | } 135 | if (ruleReport.isDefault) { 136 | return `No rule allows the usage of external module '${ 137 | dependency.baseModule 138 | }' in elements ${elementMessage(file)}`; 139 | } 140 | 141 | const fileReport = `is not allowed in ${ruleElementMessage( 142 | ruleReport.element, 143 | file.capturedValues, 144 | )}. Disallowed in rule ${ruleReport.index + 1}`; 145 | 146 | if (ruleData.report) { 147 | return `Usage of ${dependencyUsageKindMessage( 148 | ruleReport.importKind, 149 | dependency, 150 | )}'${getErrorReportMessage(ruleData.report)}' from external module '${ 151 | dependency.baseModule 152 | }' ${fileReport}`; 153 | } 154 | return `Usage of ${dependencyUsageKindMessage(ruleReport.importKind, dependency, { 155 | suffix: " from ", 156 | })}external module '${dependency.baseModule}' ${fileReport}`; 157 | } 158 | 159 | module.exports = dependencyRule( 160 | { 161 | ruleName: RULE_EXTERNAL, 162 | description: `Check allowed external dependencies by element type`, 163 | schema: rulesOptionsSchema({ 164 | targetMatcherOptions: { 165 | type: "object", 166 | properties: { 167 | specifiers: { 168 | type: "array", 169 | items: { 170 | type: "string", 171 | }, 172 | }, 173 | path: { 174 | oneOf: [ 175 | { 176 | type: "string", 177 | }, 178 | { 179 | type: "array", 180 | items: { 181 | type: "string", 182 | }, 183 | }, 184 | ], 185 | }, 186 | }, 187 | additionalProperties: false, 188 | }, 189 | }), 190 | }, 191 | function ({ dependency, file, node, context, options }) { 192 | if (dependency.isExternal) { 193 | const ruleData = elementRulesAllowExternalDependency( 194 | file, 195 | { ...dependency, specifiers: getSpecifiers(node) }, 196 | options, 197 | ); 198 | if (!ruleData.result) { 199 | context.report({ 200 | message: errorMessage(ruleData, file, dependency), 201 | node: node, 202 | }); 203 | } 204 | } 205 | }, 206 | { 207 | validateRules: { onlyMainKey: true }, 208 | }, 209 | ); 210 | -------------------------------------------------------------------------------- /src/rules/no-ignored.js: -------------------------------------------------------------------------------- 1 | const { RULE_NO_IGNORED } = require("../constants/settings"); 2 | 3 | const dependencyRule = require("../rules-factories/dependency-rule"); 4 | 5 | module.exports = dependencyRule( 6 | { 7 | ruleName: RULE_NO_IGNORED, 8 | description: `Prevent importing ignored files from recognized elements`, 9 | }, 10 | function ({ dependency, node, context }) { 11 | if (dependency.isIgnored) { 12 | context.report({ 13 | message: `Importing ignored files is not allowed`, 14 | node: node, 15 | }); 16 | } 17 | }, 18 | { 19 | validate: false, 20 | }, 21 | ); 22 | -------------------------------------------------------------------------------- /src/rules/no-private.js: -------------------------------------------------------------------------------- 1 | const { RULE_NO_PRIVATE } = require("../constants/settings"); 2 | 3 | const dependencyRule = require("../rules-factories/dependency-rule"); 4 | 5 | const { customErrorMessage, elementMessage } = require("../helpers/messages"); 6 | 7 | function errorMessage(file, dependency, options) { 8 | if (options.message) { 9 | return customErrorMessage(options.message, file, dependency); 10 | } 11 | return `Dependency is private of element ${elementMessage(dependency.parents[0])}`; 12 | } 13 | 14 | module.exports = dependencyRule( 15 | { 16 | ruleName: RULE_NO_PRIVATE, 17 | description: `Prevent importing private elements of another element`, 18 | schema: [ 19 | { 20 | type: "object", 21 | properties: { 22 | allowUncles: { 23 | type: "boolean", 24 | }, 25 | message: { 26 | type: "string", 27 | }, 28 | }, 29 | additionalProperties: false, 30 | }, 31 | ], 32 | }, 33 | function ({ file, dependency, node, context, options }) { 34 | if ( 35 | !dependency.isIgnored && 36 | dependency.isLocal && 37 | dependency.type && 38 | dependency.parents.length && 39 | dependency.relationship !== "internal" && 40 | dependency.relationship !== "child" && 41 | dependency.relationship !== "brother" && 42 | (!options?.allowUncles || dependency.relationship !== "uncle") 43 | ) { 44 | context.report({ 45 | message: errorMessage(file, dependency, options), 46 | node: node, 47 | }); 48 | } 49 | }, 50 | { 51 | validate: false, 52 | }, 53 | ); 54 | -------------------------------------------------------------------------------- /src/rules/no-unknown-files.js: -------------------------------------------------------------------------------- 1 | const { RULE_NO_UNKNOWN_FILES } = require("../constants/settings"); 2 | 3 | const { fileInfo } = require("../core/elementsInfo"); 4 | const { meta } = require("../helpers/rules"); 5 | 6 | module.exports = { 7 | ...meta({ 8 | ruleName: RULE_NO_UNKNOWN_FILES, 9 | description: `Prevent creating files not recognized as any of the element types`, 10 | }), 11 | 12 | create: function (context) { 13 | const file = fileInfo(context); 14 | if (file.type || file.isIgnored) { 15 | return {}; 16 | } 17 | return { 18 | Program: (node) => { 19 | context.report({ 20 | message: `File is not of any known element type`, 21 | node: node, 22 | }); 23 | }, 24 | }; 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /src/rules/no-unknown.js: -------------------------------------------------------------------------------- 1 | const { RULE_NO_UNKNOWN } = require("../constants/settings"); 2 | 3 | const dependencyRule = require("../rules-factories/dependency-rule"); 4 | 5 | module.exports = dependencyRule( 6 | { 7 | ruleName: RULE_NO_UNKNOWN, 8 | description: `Prevent importing unknown elements from the known ones`, 9 | }, 10 | function ({ dependency, node, context }) { 11 | if (!dependency.isIgnored && dependency.isLocal && !dependency.type) { 12 | context.report({ 13 | message: `Importing unknown elements is not allowed`, 14 | node: node, 15 | }); 16 | } 17 | }, 18 | { 19 | validate: false, 20 | }, 21 | ); 22 | -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/components/atoms/atom-a/AtomA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/components/atoms/atom-a/AtomA.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/components/atoms/atom-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/components/atoms/atom-a/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/components/atoms/atom-b/AtomB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/components/atoms/atom-b/AtomB.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/components/atoms/atom-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/components/atoms/atom-b/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/components/molecules/molecule-a/MoleculeA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/components/molecules/molecule-a/MoleculeA.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/components/molecules/molecule-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/components/molecules/molecule-a/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/components/molecules/molecule-b/MoleculeB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/components/molecules/molecule-b/MoleculeB.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/components/molecules/molecule-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/components/molecules/molecule-b/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-a/ModuleA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-a/ModuleA.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-a/components/atoms/atom-e/AtomE.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-a/components/atoms/atom-e/AtomE.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-a/components/atoms/atom-e/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-a/components/atoms/atom-e/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-a/components/atoms/atom-f/AtomF.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-a/components/atoms/atom-f/AtomF.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-a/components/atoms/atom-f/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-a/components/atoms/atom-f/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-a/components/molecules/molecule-e/MoleculeE.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-a/components/molecules/molecule-e/MoleculeE.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-a/components/molecules/molecule-e/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-a/components/molecules/molecule-e/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-a/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-b/ModuleB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-b/ModuleB.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-b/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-b/modules/module-h/ModuleH.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-b/modules/module-h/ModuleH.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-b/modules/module-h/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-b/modules/module-h/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-b/modules/module-h/modules/module-j/ModuleJ.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-b/modules/module-h/modules/module-j/ModuleJ.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-b/modules/module-h/modules/module-j/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-b/modules/module-h/modules/module-j/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-b/modules/module-i/ModuleI.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-b/modules/module-i/ModuleI.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-a/modules/module-b/modules/module-i/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-a/modules/module-b/modules/module-i/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/components/atoms/atom-c/AtomC.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/components/atoms/atom-c/AtomC.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/components/atoms/atom-c/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/components/atoms/atom-c/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/components/atoms/atom-d/AtomD.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/components/atoms/atom-d/AtomD.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/components/atoms/atom-d/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/components/atoms/atom-d/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/components/molecules/molecule-c/MoleculeC.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/components/molecules/molecule-c/MoleculeC.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/components/molecules/molecule-c/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/components/molecules/molecule-c/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/components/molecules/molecule-d/MoleculeD.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/components/molecules/molecule-d/MoleculeD.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/components/molecules/molecule-d/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/components/molecules/molecule-d/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/modules/module-c/ModuleC.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/modules/module-c/ModuleC.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/modules/module-c/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/modules/module-c/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/modules/module-d/ModuleD.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/modules/module-d/ModuleD.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/modules/module-d/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/modules/module-d/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/modules/module-d/modules/module-e/ModuleE.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/modules/module-d/modules/module-e/ModuleE.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/modules/module-d/modules/module-e/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/modules/module-d/modules/module-e/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/modules/module-d/modules/module-e/modules/module-g/ModuleG.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/modules/module-d/modules/module-e/modules/module-g/ModuleG.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/modules/module-d/modules/module-e/modules/module-g/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/modules/module-d/modules/module-e/modules/module-g/index.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/modules/module-d/modules/module-f/ModuleF.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/modules/module-d/modules/module-f/ModuleF.js -------------------------------------------------------------------------------- /test/fixtures/base-pattern/domains/domain-b/modules/module-d/modules/module-f/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/base-pattern/domains/domain-b/modules/module-d/modules/module-f/index.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/components/atoms/atom-a/AtomA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/components/atoms/atom-a/AtomA.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/components/atoms/atom-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/components/atoms/atom-a/index.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/components/atoms/atom-b/AtomB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/components/atoms/atom-b/AtomB.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/components/atoms/atom-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/components/atoms/atom-b/index.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/components/molecules/molecule-a/MoleculeA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/components/molecules/molecule-a/MoleculeA.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/components/molecules/molecule-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/components/molecules/molecule-a/index.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/components/molecules/molecule-b/MoleculeB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/components/molecules/molecule-b/MoleculeB.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/components/molecules/molecule-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/components/molecules/molecule-b/index.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/foo.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/foo.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/foo2.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/foo2.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/helpers/data/parse.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/helpers/data/parse.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/helpers/data/sort.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/helpers/data/sort.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/helpers/permissions/roles.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/helpers/permissions/roles.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/index.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/modules/module-a/ModuleA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/modules/module-a/ModuleA.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/modules/module-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/modules/module-a/index.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/modules/module-b/ModuleB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/modules/module-b/ModuleB.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/modules/module-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/modules/module-b/index.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/modules/module-b/modules/module-c/ModuleC.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/modules/module-b/modules/module-c/ModuleC.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/modules/module-b/modules/module-c/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/modules/module-b/modules/module-c/index.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/modules/module-b/modules/module-c/modules/module-e/ModuleE.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/modules/module-b/modules/module-c/modules/module-e/ModuleE.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/modules/module-b/modules/module-c/modules/module-e/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/modules/module-b/modules/module-c/modules/module-e/index.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/modules/module-b/modules/module-d/ModuleD.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/modules/module-b/modules/module-d/ModuleD.js -------------------------------------------------------------------------------- /test/fixtures/docs-examples/modules/module-b/modules/module-d/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/docs-examples/modules/module-b/modules/module-d/index.js -------------------------------------------------------------------------------- /test/fixtures/layered/modules/module-a/components/ComponentA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/layered/modules/module-a/components/ComponentA.js -------------------------------------------------------------------------------- /test/fixtures/layered/modules/module-a/helpers.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/layered/modules/module-a/helpers.js -------------------------------------------------------------------------------- /test/fixtures/layered/modules/module-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/layered/modules/module-a/index.js -------------------------------------------------------------------------------- /test/fixtures/layered/modules/module-b/components/ComponentB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/layered/modules/module-b/components/ComponentB.js -------------------------------------------------------------------------------- /test/fixtures/layered/modules/module-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/layered/modules/module-b/index.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/app.module.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/app.module.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/cats/cats.controller.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/cats/cats.controller.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/cats/cats.module.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/cats/cats.module.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/cats/cats.service.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/cats/cats.service.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/cats/dto/create-cat.dto.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/cats/dto/create-cat.dto.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/cats/interfaces/cats.interface.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/cats/interfaces/cats.interface.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/cats/models/persian-cat.model.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/cats/models/persian-cat.model.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/cats/models/siamese-cat.dto.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/cats/models/siamese-cat.dto.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/common/decorators/roles.decorator.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/common/decorators/roles.decorator.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/common/filters/http-exception.filter.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/common/filters/http-exception.filter.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/common/guards/roles.guards.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/common/guards/roles.guards.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/core/core.controller.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/core/core.controller.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/core/core.model.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/core/core.model.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/core/core.module.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/core/core.module.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/core/interceptors/logging.interceptor.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/core/interceptors/logging.interceptor.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/core/interceptors/transform.interceptor.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/core/interceptors/transform.interceptor.js -------------------------------------------------------------------------------- /test/fixtures/nestjs-example/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/nestjs-example/main.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/ComponentD/ComponentD.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/ComponentD/ComponentD.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/ComponentD/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/ComponentD/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/ComponentD/module-a.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/ComponentD/module-a.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-a/ComponentA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-a/ComponentA.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-a/components/component-c/ComponentC.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-a/components/component-c/ComponentC.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-a/components/component-c/components/component-d/ComponentD.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-a/components/component-c/components/component-d/ComponentD.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-a/components/component-c/components/component-d/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-a/components/component-c/components/component-d/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-a/components/component-c/components/component-e/ComponentE.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-a/components/component-c/components/component-e/ComponentE.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-a/components/component-c/components/component-e/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-a/components/component-c/components/component-e/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-a/components/component-c/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-a/components/component-c/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-a/helpers/helper-a/HelperA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-a/helpers/helper-a/HelperA.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-a/helpers/helper-a/helpers/helper-b/HelperB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-a/helpers/helper-a/helpers/helper-b/HelperB.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-a/helpers/helper-a/helpers/helper-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-a/helpers/helper-a/helpers/helper-b/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-a/helpers/helper-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-a/helpers/helper-a/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-a/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-b/Component.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-b/Component.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-b/ComponentB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-b/ComponentB.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-b/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-b/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-b/main.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-c/component-c.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-c/component-c.js -------------------------------------------------------------------------------- /test/fixtures/one-level/components/component-c/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/components/component-c/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/foo/foo2/foo2.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/foo/foo2/foo2.js -------------------------------------------------------------------------------- /test/fixtures/one-level/foo/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/foo/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/helpers/helper-a/HelperA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/helpers/helper-a/HelperA.js -------------------------------------------------------------------------------- /test/fixtures/one-level/helpers/helper-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/helpers/helper-a/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/helpers/helper-a/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/helpers/helper-a/main.js -------------------------------------------------------------------------------- /test/fixtures/one-level/helpers/helper-b/HelperB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/helpers/helper-b/HelperB.js -------------------------------------------------------------------------------- /test/fixtures/one-level/helpers/helper-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/helpers/helper-b/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/helpers/helper-b/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/helpers/helper-b/main.js -------------------------------------------------------------------------------- /test/fixtures/one-level/helpers/module-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/helpers/module-a/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/module-a-helpers/helper-1/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/module-a-helpers/helper-1/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/module-a-helpers/helper-2/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/module-a-helpers/helper-2/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/modules/ModuleC/ModuleC.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/modules/ModuleC/ModuleC.js -------------------------------------------------------------------------------- /test/fixtures/one-level/modules/module-a/ModuleA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/modules/module-a/ModuleA.js -------------------------------------------------------------------------------- /test/fixtures/one-level/modules/module-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/modules/module-a/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/modules/module-b/ModuleB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/modules/module-b/ModuleB.js -------------------------------------------------------------------------------- /test/fixtures/one-level/modules/module-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/one-level/modules/module-b/index.js -------------------------------------------------------------------------------- /test/fixtures/one-level/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "outDir": "dist", 6 | "baseUrl": ".", 7 | "paths": { 8 | "modules/*": ["modules/*"], 9 | "components/*": ["components/*"], 10 | "helpers/*": ["helpers/*"], 11 | "foo/*": ["foo/*"] 12 | }, 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/atoms/atom-a/AtomA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/atoms/atom-a/AtomA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/atoms/atom-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/atoms/atom-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/atoms/atom-b/AtomB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/atoms/atom-b/AtomB.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/atoms/atom-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/atoms/atom-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/atoms/atom-b/subfolder-1/subfile-1.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/atoms/atom-b/subfolder-1/subfile-1.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/atoms/atom-b/subfolder-1/subfolder-2/subfile-2.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/atoms/atom-b/subfolder-1/subfolder-2/subfile-2.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/layouts/layout-a/LayoutA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/layouts/layout-a/LayoutA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/layouts/layout-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/layouts/layout-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/layouts/layout-b/LayoutB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/layouts/layout-b/LayoutB.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/layouts/layout-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/layouts/layout-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/molecules/molecule-a/MoleculeA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/molecules/molecule-a/MoleculeA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/molecules/molecule-a/components/atoms/atom-c/AtomC.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/molecules/molecule-a/components/atoms/atom-c/AtomC.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/molecules/molecule-a/components/atoms/atom-c/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/molecules/molecule-a/components/atoms/atom-c/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/molecules/molecule-a/components/molecules/molecule-c/MoleculeC.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/molecules/molecule-a/components/molecules/molecule-c/MoleculeC.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/molecules/molecule-a/components/molecules/molecule-c/components/molecules/molecule-d/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/molecules/molecule-a/components/molecules/molecule-c/components/molecules/molecule-d/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/molecules/molecule-a/components/molecules/molecule-c/components/molecules/molecule-d/moleculeD.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/molecules/molecule-a/components/molecules/molecule-c/components/molecules/molecule-d/moleculeD.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/molecules/molecule-a/components/molecules/molecule-c/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/molecules/molecule-a/components/molecules/molecule-c/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/molecules/molecule-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/molecules/molecule-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/molecules/molecule-b/MoleculeB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/molecules/molecule-b/MoleculeB.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/components/molecules/molecule-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/components/molecules/molecule-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/helpers/helper-a/helpers/helper-c/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/helpers/helper-a/helpers/helper-c/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/helpers/helper-a/helpers/helper-c/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/helpers/helper-a/helpers/helper-c/main.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/helpers/helper-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/helpers/helper-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/helpers/helper-a/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/helpers/helper-a/main.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/helpers/helper-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/helpers/helper-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/helpers/helper-b/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/helpers/helper-b/main.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-a/module-a/ModuleA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-a/module-a/ModuleA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-a/module-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-a/module-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-a/module-a/subfolder-1/subfile-1.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-a/module-a/subfolder-1/subfile-1.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-a/module-a/subfolder-1/subfolder-2/ModuleA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-a/module-a/subfolder-1/subfolder-2/ModuleA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-a/module-a/subfolder-1/subfolder-2/subfile-2.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-a/module-a/subfolder-1/subfolder-2/subfile-2.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-a/module-a/submodules/module-c/ModuleC.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-a/module-a/submodules/module-c/ModuleC.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-a/module-a/submodules/module-c/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-a/module-a/submodules/module-c/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-a/module-a/submodules/module-c/submodules/module-d/ModuleD.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-a/module-a/submodules/module-c/submodules/module-d/ModuleD.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-a/module-a/submodules/module-c/submodules/module-d/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-a/module-a/submodules/module-c/submodules/module-d/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-a/module-a/submodules/module-c/submodules/module-d/subfolder-1/subfile-1.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-a/module-a/submodules/module-c/submodules/module-d/subfolder-1/subfile-1.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-a/module-b/ModuleB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-a/module-b/ModuleB.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-a/module-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-a/module-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-b/module-a/ModuleA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-b/module-a/ModuleA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-b/module-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-b/module-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-b/module-b/ModuleB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-b/module-b/ModuleB.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/domain-b/module-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/domain-b/module-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/pages/page-a/ModuleA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/pages/page-a/ModuleA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/pages/page-a/PageA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/pages/page-a/PageA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/pages/page-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/pages/page-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/pages/page-b/PageB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/pages/page-b/PageB.js -------------------------------------------------------------------------------- /test/fixtures/two-levels-with-private/modules/pages/page-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels-with-private/modules/pages/page-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/atoms/atom-a/AtomA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/atoms/atom-a/AtomA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/atoms/atom-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/atoms/atom-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/atoms/atom-b/AtomB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/atoms/atom-b/AtomB.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/atoms/atom-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/atoms/atom-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/atoms/atom-b/subfolder-1/subfile-1.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/atoms/atom-b/subfolder-1/subfile-1.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/atoms/atom-b/subfolder-1/subfolder-2/subfile-2.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/atoms/atom-b/subfolder-1/subfolder-2/subfile-2.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/layouts/layout-a/LayoutA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/layouts/layout-a/LayoutA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/layouts/layout-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/layouts/layout-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/layouts/layout-b/LayoutB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/layouts/layout-b/LayoutB.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/layouts/layout-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/layouts/layout-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/molecules/molecule-a/MoleculeA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/molecules/molecule-a/MoleculeA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/molecules/molecule-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/molecules/molecule-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/molecules/molecule-b/MoleculeB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/molecules/molecule-b/MoleculeB.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/components/molecules/molecule-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/components/molecules/molecule-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/helpers/helper-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/helpers/helper-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/helpers/helper-a/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/helpers/helper-a/main.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/helpers/helper-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/helpers/helper-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/helpers/helper-b/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/helpers/helper-b/main.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/domain-a/module-a/ModuleA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/domain-a/module-a/ModuleA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/domain-a/module-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/domain-a/module-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/domain-a/module-a/subfolder-1/subfile-1.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/domain-a/module-a/subfolder-1/subfile-1.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/domain-a/module-a/subfolder-1/subfolder-2/ModuleA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/domain-a/module-a/subfolder-1/subfolder-2/ModuleA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/domain-a/module-a/subfolder-1/subfolder-2/subfile-2.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/domain-a/module-a/subfolder-1/subfolder-2/subfile-2.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/domain-a/module-b/ModuleB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/domain-a/module-b/ModuleB.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/domain-a/module-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/domain-a/module-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/domain-b/module-a/ModuleA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/domain-b/module-a/ModuleA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/domain-b/module-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/domain-b/module-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/domain-b/module-b/ModuleB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/domain-b/module-b/ModuleB.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/domain-b/module-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/domain-b/module-b/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/pages/page-a/ModuleA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/pages/page-a/ModuleA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/pages/page-a/PageA.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/pages/page-a/PageA.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/pages/page-a/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/pages/page-a/index.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/pages/page-b/PageB.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/pages/page-b/PageB.js -------------------------------------------------------------------------------- /test/fixtures/two-levels/modules/pages/page-b/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javierbrea/eslint-plugin-boundaries/400796330d29b47a3cd0c6c016a3050e6fe6e2fe/test/fixtures/two-levels/modules/pages/page-b/index.js -------------------------------------------------------------------------------- /test/rules/docs-examples/element-types.spec.js: -------------------------------------------------------------------------------- 1 | const { ELEMENT_TYPES: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | const { elementTypesNoRuleMessage } = require("../../support/messages"); 4 | 5 | const rule = require(`../../../src/rules/${RULE}`); 6 | 7 | const { absoluteFilePath } = pathResolvers("docs-examples"); 8 | 9 | const settings = SETTINGS.docsExamples; 10 | 11 | const options = [ 12 | { 13 | // disallow all local imports by default 14 | default: "disallow", 15 | rules: [ 16 | { 17 | // from helper elements 18 | from: ["helpers"], 19 | // allow importing helper elements 20 | allow: ["helpers"], 21 | }, 22 | { 23 | // from component elements 24 | from: ["components"], 25 | allow: [ 26 | // allow importing components of the same family 27 | ["components", { family: "${family}" }], 28 | // allow importing helpers with captured category "data" 29 | ["helpers", { category: "data" }], 30 | ], 31 | }, 32 | { 33 | // from components with captured family "molecule" 34 | from: [["components", { family: "molecule" }]], 35 | allow: [ 36 | // allow importing components with captured family "atom" 37 | ["components", { family: "atom" }], 38 | ], 39 | }, 40 | { 41 | // from modules 42 | from: ["modules"], 43 | allow: ["helpers", "components", "modules"], 44 | }, 45 | ], 46 | }, 47 | ]; 48 | 49 | const ruleTester = createRuleTester(settings); 50 | 51 | ruleTester.run(RULE, rule, { 52 | valid: [ 53 | // helper can import helper 54 | { 55 | filename: absoluteFilePath("helpers/permissions/roles.js"), 56 | code: "import { someParser } from 'helpers/data/parse'", 57 | options, 58 | }, 59 | // Components can import components of the same family 60 | { 61 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 62 | code: "import AtomB from 'components/atoms/atom-b'", 63 | options, 64 | }, 65 | // Components can import helpers of "data" category 66 | { 67 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 68 | code: "import { someParser } from 'helpers/data/parse'", 69 | options, 70 | }, 71 | // Components of family "molecule" can import components of family "atom" 72 | { 73 | filename: absoluteFilePath("components/molecules/molecule-a/MoleculeA.js"), 74 | code: "import AtomA from 'components/atoms/atoms-a'", 75 | options, 76 | }, 77 | // Modules can import helpers 78 | { 79 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 80 | code: "import { someParser } from 'helpers/data/parse'", 81 | options, 82 | }, 83 | // Modules can import components 84 | { 85 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 86 | code: "import AtomA from 'components/atoms/atom-a'", 87 | options, 88 | }, 89 | // Modules can import another modules: 90 | { 91 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 92 | code: "import ModuleB from 'modules/module-b'", 93 | options, 94 | }, 95 | ], 96 | invalid: [ 97 | // Helpers can't import component 98 | { 99 | filename: absoluteFilePath("helpers/permissions/roles.js"), 100 | code: "import AtomA from 'components/atoms/atom-a'", 101 | options, 102 | errors: [ 103 | { 104 | message: elementTypesNoRuleMessage({ 105 | file: "'helpers' with category 'permissions' and elementName 'roles'", 106 | dep: "'components' with family 'atoms' and elementName 'atom-a'", 107 | }), 108 | type: "Literal", 109 | }, 110 | ], 111 | }, 112 | // Helpers can't import modules 113 | { 114 | filename: absoluteFilePath("helpers/permissions/roles.js"), 115 | code: "import ModuleA from 'modules/module-a'", 116 | options, 117 | errors: [ 118 | { 119 | message: elementTypesNoRuleMessage({ 120 | file: "'helpers' with category 'permissions' and elementName 'roles'", 121 | dep: "'modules' with elementName 'module-a'", 122 | }), 123 | type: "Literal", 124 | }, 125 | ], 126 | }, 127 | // Components can't import components of another family 128 | { 129 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 130 | code: "import MoleculeA from 'components/molecules/molecule-a'", 131 | options, 132 | errors: [ 133 | { 134 | message: elementTypesNoRuleMessage({ 135 | file: "'components' with family 'atoms' and elementName 'atom-a'", 136 | dep: "'components' with family 'molecules' and elementName 'molecule-a'", 137 | }), 138 | type: "Literal", 139 | }, 140 | ], 141 | }, 142 | // Components can't import helpers of a category different to "data" 143 | { 144 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 145 | code: "import { roleHasPermissions } from 'helpers/permissions/roles'", 146 | options, 147 | errors: [ 148 | { 149 | message: elementTypesNoRuleMessage({ 150 | file: "'components' with family 'atoms' and elementName 'atom-a'", 151 | dep: "'helpers' with category 'permissions' and elementName 'roles'", 152 | }), 153 | type: "Literal", 154 | }, 155 | ], 156 | }, 157 | // Components can't import modules 158 | { 159 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 160 | code: "import ModuleA from 'modules/module-a'", 161 | options, 162 | errors: [ 163 | { 164 | message: elementTypesNoRuleMessage({ 165 | file: "'components' with family 'atoms' and elementName 'atom-a'", 166 | dep: "'modules' with elementName 'module-a'", 167 | }), 168 | type: "Literal", 169 | }, 170 | ], 171 | }, 172 | ], 173 | }); 174 | -------------------------------------------------------------------------------- /test/rules/docs-examples/entry-point.spec.js: -------------------------------------------------------------------------------- 1 | const { ENTRY_POINT: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | const { customErrorMessage, entryPointNoRuleMessage } = require("../../support/messages"); 4 | 5 | const rule = require(`../../../src/rules/${RULE}`); 6 | 7 | const { absoluteFilePath } = pathResolvers("docs-examples"); 8 | 9 | const settings = SETTINGS.docsExamples; 10 | 11 | const options = [ 12 | { 13 | // disallow all entry-points by default 14 | default: "disallow", 15 | rules: [ 16 | { 17 | // when importing helpers 18 | target: ["helpers"], 19 | // allow everything (helpers are single files) 20 | allow: "*", 21 | }, 22 | { 23 | // when importing components or modules 24 | target: ["components", "modules"], 25 | // only allow index.js 26 | allow: "index.js", 27 | }, 28 | ], 29 | }, 30 | ]; 31 | 32 | const errorMessages = {}; 33 | 34 | const ruleTester = createRuleTester(settings); 35 | 36 | ruleTester.run(RULE, rule, { 37 | valid: [ 38 | // helper file can be imported 39 | { 40 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 41 | code: "import { someParser } from 'helpers/data/parse'", 42 | options, 43 | }, 44 | // index.js from components can be imported 45 | { 46 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 47 | code: "import ComponentB from 'components/atoms/atom-b'", 48 | options, 49 | }, 50 | // index.js from components can be imported 51 | { 52 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 53 | code: "import ComponentB from 'components/atoms/atom-b/index.js'", 54 | options, 55 | }, 56 | // index.js from modules can be imported 57 | { 58 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 59 | code: "import ModuleB from 'modules/module-b'", 60 | options, 61 | }, 62 | ], 63 | invalid: [ 64 | // Any other file than index.js can't be imported from components 65 | { 66 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 67 | code: "import AtomA from 'components/atoms/atom-a/AtomA'", 68 | options, 69 | errors: [ 70 | { 71 | message: customErrorMessage( 72 | errorMessages, 73 | 0, 74 | entryPointNoRuleMessage({ 75 | entryPoint: "AtomA.js", 76 | dep: "'components' with family 'atoms' and elementName 'atom-a'", 77 | }), 78 | ), 79 | type: "Literal", 80 | }, 81 | ], 82 | }, 83 | // Any other file than index.js can't be imported from modules 84 | { 85 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 86 | code: "import ModuleB from 'modules/module-b/ModuleB'", 87 | options, 88 | errors: [ 89 | { 90 | message: customErrorMessage( 91 | errorMessages, 92 | 1, 93 | entryPointNoRuleMessage({ 94 | entryPoint: "ModuleB.js", 95 | dep: "'modules' with elementName 'module-b'", 96 | }), 97 | ), 98 | type: "Literal", 99 | }, 100 | ], 101 | }, 102 | ], 103 | }); 104 | -------------------------------------------------------------------------------- /test/rules/docs-examples/external.spec.js: -------------------------------------------------------------------------------- 1 | const { EXTERNAL: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | const { externalNoRuleMessage } = require("../../support/messages"); 4 | 5 | const rule = require(`../../../src/rules/${RULE}`); 6 | 7 | const { absoluteFilePath } = pathResolvers("docs-examples"); 8 | 9 | const settings = SETTINGS.docsExamples; 10 | 11 | const options = [ 12 | { 13 | // disallow all external imports by default 14 | default: "disallow", 15 | rules: [ 16 | { 17 | // from helper elements 18 | from: ["helpers"], 19 | // allow importing moment 20 | allow: ["moment"], 21 | }, 22 | { 23 | // from component elements 24 | from: ["components"], 25 | allow: [ 26 | // allow importing react 27 | "react", 28 | // allow importing any @material-ui module 29 | "@material-ui/*", 30 | ], 31 | }, 32 | { 33 | // from components of family "molecules" 34 | from: [["components", { family: "molecules" }]], 35 | disallow: [ 36 | // disallow importing @material-ui/icons 37 | "@material-ui/icons", 38 | ], 39 | }, 40 | { 41 | // from modules 42 | from: ["modules"], 43 | allow: [ 44 | // allow importing react 45 | "react", 46 | // allow importing useHistory, Switch and Route from react-router-dom 47 | ["react-router-dom", { specifiers: ["useHistory", "Switch", "Route"] }], 48 | ], 49 | }, 50 | ], 51 | }, 52 | ]; 53 | 54 | const ruleTester = createRuleTester(settings); 55 | 56 | ruleTester.run(RULE, rule, { 57 | valid: [ 58 | // Helpers can import moment 59 | { 60 | filename: absoluteFilePath("helpers/data/parse.js"), 61 | code: "import moment from 'moment'", 62 | options, 63 | }, 64 | // Components can import react 65 | { 66 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 67 | code: "import React from 'react'", 68 | options, 69 | }, 70 | // Components can import @material-ui/core 71 | { 72 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 73 | code: "import { Button } from '@material-ui/core'", 74 | options, 75 | }, 76 | // Modules can import react 77 | { 78 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 79 | code: "import React from 'react'", 80 | options, 81 | }, 82 | // Modules can import `useHistory` from `react-router-dom` 83 | { 84 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 85 | code: "import { useHistory } from 'react-router-dom'", 86 | options, 87 | }, 88 | ], 89 | invalid: [ 90 | // Helpers can't import react 91 | { 92 | filename: absoluteFilePath("helpers/data/parse.js"), 93 | code: "import React from 'react'", 94 | options, 95 | errors: [ 96 | { 97 | message: externalNoRuleMessage({ 98 | file: "'helpers' with category 'data' and elementName 'parse'", 99 | dep: "react", 100 | }), 101 | type: "Literal", 102 | }, 103 | ], 104 | }, 105 | // Helpers can't import specifier from react 106 | { 107 | filename: absoluteFilePath("helpers/data/parse.js"), 108 | code: "import { useMemo } from 'react'", 109 | options, 110 | errors: [ 111 | { 112 | message: externalNoRuleMessage({ 113 | file: "'helpers' with category 'data' and elementName 'parse'", 114 | dep: "react", 115 | }), 116 | type: "Literal", 117 | }, 118 | ], 119 | }, 120 | // Components can't import `moment` 121 | { 122 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 123 | code: "import moment from 'moment'", 124 | options, 125 | errors: [ 126 | { 127 | message: externalNoRuleMessage({ 128 | file: "'components' with family 'atoms' and elementName 'atom-a'", 129 | dep: "moment", 130 | }), 131 | type: "Literal", 132 | }, 133 | ], 134 | }, 135 | // Components of family "molecules" can't import `@material-ui/icons` 136 | { 137 | filename: absoluteFilePath("components/molecules/molecule-a/MoleculeA.js"), 138 | code: "import { Info } from '@material-ui/icons'", 139 | options, 140 | errors: [ 141 | { 142 | message: 143 | "Usage of external module '@material-ui/icons' is not allowed in elements of type 'components' with family 'molecules'. Disallowed in rule 3", 144 | type: "Literal", 145 | }, 146 | ], 147 | }, 148 | // Modules can't import `withRouter` from `react-router-dom` 149 | { 150 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 151 | code: "import { withRouter } from 'react-router-dom'", 152 | options, 153 | errors: [ 154 | { 155 | message: externalNoRuleMessage({ 156 | file: "'modules' with elementName 'module-a'", 157 | dep: "react-router-dom", 158 | }), 159 | type: "Literal", 160 | }, 161 | ], 162 | }, 163 | ], 164 | }); 165 | -------------------------------------------------------------------------------- /test/rules/docs-examples/no-ignored.spec.js: -------------------------------------------------------------------------------- 1 | const { NO_IGNORED: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | 4 | const rule = require(`../../../src/rules/${RULE}`); 5 | 6 | const settings = SETTINGS.docsExamples; 7 | const { absoluteFilePath } = pathResolvers("docs-examples"); 8 | 9 | const ERROR_MESSAGE = "Importing ignored files is not allowed"; 10 | 11 | const test = (customSettings) => { 12 | const ruleTester = createRuleTester(customSettings); 13 | 14 | ruleTester.run(RULE, rule, { 15 | valid: [ 16 | // `index.js` file is not recognized as any element, so it can import `foo.js` 17 | { 18 | filename: absoluteFilePath("index.js"), 19 | code: "import foo from './foo'", 20 | }, 21 | // `foo2.js` file is not ignored, so it can be imported by helpers 22 | { 23 | filename: absoluteFilePath("helpers/data/sort.js"), 24 | code: "import foo2 from '../../foo2'", 25 | errors: [ 26 | { 27 | message: ERROR_MESSAGE, 28 | type: "Literal", 29 | }, 30 | ], 31 | }, 32 | ], 33 | invalid: [ 34 | // `foo.js` file is ignored, so it can't be imported by helpers 35 | { 36 | filename: absoluteFilePath("helpers/data/sort.js"), 37 | code: "import foo from '../../foo'", 38 | errors: [ 39 | { 40 | message: ERROR_MESSAGE, 41 | type: "Literal", 42 | }, 43 | ], 44 | }, 45 | ], 46 | }); 47 | }; 48 | 49 | // ignore foo 50 | test({ 51 | ...settings, 52 | "boundaries/ignore": ["**/foo.js"], 53 | }); 54 | 55 | // include other file 56 | test({ 57 | ...settings, 58 | "boundaries/include": ["**/foo2.js", "**/sort.js"], 59 | }); 60 | 61 | // include all other files except "foo" 62 | test({ 63 | ...settings, 64 | "boundaries/include": ["**/foo2.js", "**/sort.js", "**/foo.js"], 65 | "boundaries/ignore": ["**/foo.js"], 66 | }); 67 | -------------------------------------------------------------------------------- /test/rules/docs-examples/no-private.spec.js: -------------------------------------------------------------------------------- 1 | const { NO_PRIVATE: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | const { noPrivateMessage } = require("../../support/messages"); 4 | 5 | const rule = require(`../../../src/rules/${RULE}`); 6 | 7 | const settings = SETTINGS.docsExamples; 8 | const { absoluteFilePath } = pathResolvers("docs-examples"); 9 | 10 | const options = [ 11 | { 12 | allowUncles: true, 13 | }, 14 | ]; 15 | 16 | const ruleTester = createRuleTester(settings); 17 | 18 | ruleTester.run(RULE, rule, { 19 | valid: [ 20 | // `module-b` can import `module-c` because it is his direct child 21 | { 22 | filename: absoluteFilePath("modules/module-b/ModuleB.js"), 23 | code: "import ModuleC from './modules/module-c'", 24 | options, 25 | }, 26 | // `module-c` can import `module-a` because it is public 27 | { 28 | filename: absoluteFilePath("modules/module-b/modules/module-c/ModuleC.js"), 29 | code: "import ModuleA from 'modules/module-a'", 30 | options, 31 | }, 32 | // `module-c` can import `module-d` because it is his brother 33 | { 34 | filename: absoluteFilePath("modules/module-b/modules/module-c/ModuleC.js"), 35 | code: "import ModuleD from '../module-d'", 36 | options, 37 | }, 38 | // `module-e` can import `module-d` because it is his uncle 39 | { 40 | filename: absoluteFilePath("modules/module-b/modules/module-c/modules/module-e/ModuleE"), 41 | code: "import ModuleD from 'modules/module-b/modules/module-d'", 42 | options, 43 | }, 44 | ], 45 | invalid: [ 46 | // `module-a` can't import `module-c` because it is child of `module-b` 47 | { 48 | filename: absoluteFilePath("modules/module-a/moduleA.js"), 49 | code: "import ModuleC from 'modules/module-b/modules/module-c'", 50 | options, 51 | errors: [ 52 | { 53 | message: noPrivateMessage({ 54 | dep: "'modules' with elementName 'module-b'", 55 | }), 56 | type: "Literal", 57 | }, 58 | ], 59 | }, 60 | // `module-b` can't import `module-e` because it is child of `module-c` (even when it is his grandchild) 61 | { 62 | filename: absoluteFilePath("modules/module-b/moduleB.js"), 63 | code: "import ModuleE from './modules/module-c/modules/module-e'", 64 | options, 65 | errors: [ 66 | { 67 | message: noPrivateMessage({ 68 | dep: "'modules' with elementName 'module-c'", 69 | }), 70 | type: "Literal", 71 | }, 72 | ], 73 | }, 74 | // `module-e` can't import `module-d` when `allowUncles` option is disabled 75 | { 76 | filename: absoluteFilePath("modules/module-b/modules/module-c/modules/module-e/ModuleE"), 77 | code: "import ModuleD from 'modules/module-b/modules/module-d'", 78 | options: [ 79 | { 80 | allowUncles: false, 81 | }, 82 | ], 83 | errors: [ 84 | { 85 | message: noPrivateMessage({ 86 | dep: "'modules' with elementName 'module-b'", 87 | }), 88 | type: "Literal", 89 | }, 90 | ], 91 | }, 92 | ], 93 | }); 94 | -------------------------------------------------------------------------------- /test/rules/docs-examples/no-unknown-files.spec.js: -------------------------------------------------------------------------------- 1 | const { NO_UNKNOWN_FILES: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | 4 | const rule = require(`../../../src/rules/${RULE}`); 5 | 6 | const settings = SETTINGS.docsExamples; 7 | const { absoluteFilePath, codeFilePath } = pathResolvers("docs-examples"); 8 | 9 | const FOO_CODE = "export default {}"; 10 | const ERROR_MESSAGE = "File is not of any known element type"; 11 | 12 | const ruleTester = createRuleTester(settings); 13 | 14 | ruleTester.run(RULE, rule, { 15 | valid: [ 16 | // Helper files are allowed 17 | { 18 | filename: absoluteFilePath("helpers/data/sort.js"), 19 | code: FOO_CODE, 20 | }, 21 | // `index.js` file is not recognized, but it is ignored in settings 22 | { 23 | filename: absoluteFilePath("index.js"), 24 | code: FOO_CODE, 25 | settings: { 26 | ...settings, 27 | "boundaries/ignore": [codeFilePath("index.js")], 28 | }, 29 | }, 30 | ], 31 | invalid: [ 32 | // `foo.js` file is not recognized, so it is not allowed 33 | { 34 | filename: absoluteFilePath("foo.js"), 35 | code: FOO_CODE, 36 | errors: [ 37 | { 38 | message: ERROR_MESSAGE, 39 | type: "Program", 40 | }, 41 | ], 42 | }, 43 | // `index.js` file is not recognized, so it is not allowed 44 | { 45 | filename: absoluteFilePath("index.js"), 46 | code: FOO_CODE, 47 | errors: [ 48 | { 49 | message: ERROR_MESSAGE, 50 | type: "Program", 51 | }, 52 | ], 53 | }, 54 | ], 55 | }); 56 | -------------------------------------------------------------------------------- /test/rules/docs-examples/no-unknown.spec.js: -------------------------------------------------------------------------------- 1 | const { NO_UNKNOWN: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | 4 | const rule = require(`../../../src/rules/${RULE}`); 5 | 6 | const settings = SETTINGS.docsExamples; 7 | const { absoluteFilePath } = pathResolvers("docs-examples"); 8 | 9 | const ERROR_MESSAGE = "Importing unknown elements is not allowed"; 10 | 11 | const ruleTester = createRuleTester(settings); 12 | 13 | ruleTester.run(RULE, rule, { 14 | valid: [ 15 | // Components can import helpers 16 | { 17 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 18 | code: "import index from '../../../helpers/data/parse'", 19 | }, 20 | // `index.js` file can import `foo.js` file because both are unknown 21 | { 22 | filename: absoluteFilePath("index.js"), 23 | code: "import foo from './foo'", 24 | }, 25 | // External dependencies can be imported 26 | { 27 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 28 | code: "import 'chalk'", 29 | }, 30 | ], 31 | invalid: [ 32 | // Helpers can't import `foo.js` file because it is unknown 33 | { 34 | filename: absoluteFilePath("helpers/data/parse.js"), 35 | code: "import foo from '../../foo'", 36 | errors: [ 37 | { 38 | message: ERROR_MESSAGE, 39 | type: "Literal", 40 | }, 41 | ], 42 | }, 43 | // Components can't import `index.js` file because it is unknown 44 | { 45 | filename: absoluteFilePath("components/atoms/atom-a/AtomA.js"), 46 | code: "import index from '../../../index'", 47 | errors: [ 48 | { 49 | message: ERROR_MESSAGE, 50 | type: "Literal", 51 | }, 52 | ], 53 | }, 54 | ], 55 | }); 56 | -------------------------------------------------------------------------------- /test/rules/layered/entry-point.spec.js: -------------------------------------------------------------------------------- 1 | const { ENTRY_POINT: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | 4 | const rule = require(`../../../src/rules/${RULE}`); 5 | 6 | const { absoluteFilePath } = pathResolvers("layered"); 7 | 8 | const settings = SETTINGS.layered; 9 | 10 | // https://github.com/javierbrea/eslint-plugin-boundaries/issues/340 11 | const options = [ 12 | { 13 | // disallow all entry-points by default 14 | default: "disallow", 15 | rules: [ 16 | { 17 | target: ["modules"], 18 | allow: "**", 19 | }, 20 | { 21 | target: [ 22 | // Any element, except the same as target 23 | ["modules", { elementName: "!(${from.elementName})" }], 24 | ], 25 | // Any file, except index.js 26 | disallow: "!(index.js)", 27 | }, 28 | ], 29 | }, 30 | ]; 31 | 32 | const ruleTester = createRuleTester(settings); 33 | 34 | ruleTester.run(RULE, rule, { 35 | valid: [ 36 | // helper can be imported inside the same module 37 | { 38 | filename: absoluteFilePath("modules/module-a/components/ComponentA.js"), 39 | code: "import { someHelper } from '../helpers.js'", 40 | options, 41 | }, 42 | // helper can be imported from the pubic module API, defined in index.js 43 | { 44 | filename: absoluteFilePath("modules/module-b/components/ComponentB.js"), 45 | code: "import { someHelper } from 'modules/module-a'", 46 | options, 47 | }, 48 | ], 49 | invalid: [ 50 | // Any other file than index.js can't be imported from other module 51 | { 52 | filename: absoluteFilePath("modules/module-b/components/ComponentB.js"), 53 | code: "import { someHelper } from 'modules/module-a/helpers.js'", 54 | options, 55 | errors: [ 56 | { 57 | message: 58 | "The entry point 'helpers.js' is not allowed in elements of type 'modules' with elementName '!(module-a)'. Disallowed in rule 2", 59 | type: "Literal", 60 | }, 61 | ], 62 | }, 63 | { 64 | filename: absoluteFilePath("modules/module-b/components/ComponentB.js"), 65 | code: "import { someHelper } from 'modules/module-a/components/ComponentA.js'", 66 | options, 67 | errors: [ 68 | { 69 | message: 70 | "The entry point 'components' is not allowed in elements of type 'modules' with elementName '!(module-a)'. Disallowed in rule 2", 71 | type: "Literal", 72 | }, 73 | ], 74 | }, 75 | ], 76 | }); 77 | -------------------------------------------------------------------------------- /test/rules/one-level/entry-point-import-kind.spec.js: -------------------------------------------------------------------------------- 1 | const { ENTRY_POINT: RULE } = require("../../../src/constants/rules"); 2 | const { TYPESCRIPT_SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | const { customErrorMessage } = require("../../support/messages"); 4 | 5 | const rule = require(`../../../src/rules/${RULE}`); 6 | 7 | const { absoluteFilePath } = pathResolvers("one-level"); 8 | 9 | const test = (settings, options, errorMessages = {}) => { 10 | const ruleTester = createRuleTester(settings); 11 | ruleTester.run(RULE, rule, { 12 | valid: [ 13 | // import value from main.js file from helper 14 | { 15 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 16 | code: "import helper from 'helpers/helper-b/main'", 17 | options, 18 | }, 19 | // import type from Component.js file from component 20 | { 21 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 22 | code: "import type ComponentB from 'components/component-b/Component.js'", 23 | options, 24 | }, 25 | // import type from Module.js file from module 26 | { 27 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 28 | code: "import type ModuleA from 'modules/module-a/Module'", 29 | options, 30 | }, 31 | // import value from Module.js file from module 32 | { 33 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 34 | code: "import ModuleA from 'modules/module-a/Module'", 35 | options, 36 | }, 37 | ], 38 | invalid: [ 39 | // import type from main.js file from helper 40 | { 41 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 42 | code: "import type HelperA from 'helpers/helper-a/main'", 43 | options, 44 | errors: [ 45 | { 46 | message: customErrorMessage(errorMessages, 0, ""), 47 | type: "Literal", 48 | }, 49 | ], 50 | }, 51 | // import value from Component.js file from component 52 | { 53 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 54 | code: "import ComponentB from 'components/component-b/Component.js'", 55 | options, 56 | errors: [ 57 | { 58 | message: customErrorMessage(errorMessages, 1, ""), 59 | type: "Literal", 60 | }, 61 | ], 62 | }, 63 | // import value from not allowed file from module 64 | { 65 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 66 | code: "import ModuleA from 'modules/module-a'", 67 | options, 68 | errors: [ 69 | { 70 | message: customErrorMessage(errorMessages, 2, ""), 71 | type: "Literal", 72 | }, 73 | ], 74 | }, 75 | // import type from not allowed file from module 76 | { 77 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 78 | code: "import type ModuleA from 'modules/module-a'", 79 | options, 80 | errors: [ 81 | { 82 | message: customErrorMessage(errorMessages, 3, ""), 83 | type: "Literal", 84 | }, 85 | ], 86 | }, 87 | ], 88 | }); 89 | }; 90 | 91 | // disallow based options 92 | 93 | test( 94 | TYPESCRIPT_SETTINGS.oneLevel, 95 | [ 96 | { 97 | default: "disallow", 98 | rules: [ 99 | { 100 | target: "helpers", 101 | allow: "main.js", 102 | importKind: "value", 103 | }, 104 | { 105 | target: "components", 106 | allow: "Component.js", 107 | importKind: "type", 108 | }, 109 | { 110 | target: "modules", 111 | allow: "Module.js", 112 | importKind: "*", 113 | }, 114 | ], 115 | }, 116 | ], 117 | { 118 | 0: "No rule allows the entry point 'main.js' in dependencies of type 'helpers' with elementName 'helper-a'", 119 | 1: "No rule allows the entry point 'Component.js' in dependencies of type 'components' with elementName 'component-b'", 120 | 2: "No rule allows the entry point 'index.js' in dependencies of type 'modules' with elementName 'module-a'", 121 | 3: "No rule allows the entry point 'index.js' in dependencies of type 'modules' with elementName 'module-a'", 122 | }, 123 | ); 124 | 125 | // allow based options 126 | 127 | test( 128 | TYPESCRIPT_SETTINGS.oneLevel, 129 | [ 130 | { 131 | default: "allow", 132 | rules: [ 133 | { 134 | target: "helpers", 135 | disallow: "!main.js", 136 | importKind: "*", 137 | }, 138 | { 139 | target: "helpers", 140 | disallow: "main.js", 141 | importKind: "type", 142 | }, 143 | { 144 | target: "components", 145 | disallow: "!Component.js", 146 | importKind: "*", 147 | }, 148 | { 149 | target: "components", 150 | disallow: "Component.js", 151 | importKind: "value", 152 | }, 153 | { 154 | target: "modules", 155 | disallow: "!Module.js", 156 | importKind: "*", 157 | }, 158 | ], 159 | }, 160 | ], 161 | { 162 | 0: "The entry point 'main.js' is not allowed in elements of type 'helpers' when importing type. Disallowed in rule 2", 163 | 1: "The entry point 'Component.js' is not allowed in elements of type 'components' when importing value. Disallowed in rule 4", 164 | 2: "The entry point 'index.js' is not allowed in elements of type 'modules' when importing value. Disallowed in rule 5", 165 | 3: "The entry point 'index.js' is not allowed in elements of type 'modules' when importing type. Disallowed in rule 5", 166 | }, 167 | ); 168 | -------------------------------------------------------------------------------- /test/rules/one-level/entry-point-template.spec.js: -------------------------------------------------------------------------------- 1 | const { ENTRY_POINT: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | const { customErrorMessage, entryPointNoRuleMessage } = require("../../support/messages"); 4 | 5 | const rule = require(`../../../src/rules/${RULE}`); 6 | 7 | const { absoluteFilePath } = pathResolvers("one-level"); 8 | 9 | const testCapture = (settings, options, errorMessages = {}) => { 10 | const ruleTester = createRuleTester(settings); 11 | ruleTester.run(RULE, rule, { 12 | valid: [ 13 | // component-c entry-point is component-c 14 | { 15 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 16 | code: "import ComponentC from 'components/component-c/component-c'", 17 | options, 18 | }, 19 | // componentD entry-point is componentD.js 20 | { 21 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 22 | code: "import ComponentD from 'components/ComponentD/ComponentD'", 23 | options, 24 | }, 25 | // helper-b entry-point is main.js 26 | { 27 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 28 | code: "import HelperA from 'helpers/helper-b/main'", 29 | options, 30 | }, 31 | // module-a can import entry-point module-a in componentD 32 | { 33 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 34 | code: "import ComponentD from 'components/ComponentD/module-a'", 35 | options, 36 | }, 37 | ], 38 | invalid: [ 39 | // import index from component-c 40 | { 41 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 42 | code: "import ComponentD from 'components/component-c'", 43 | options, 44 | errors: [ 45 | { 46 | message: customErrorMessage( 47 | errorMessages, 48 | 0, 49 | entryPointNoRuleMessage({ 50 | entryPoint: "index.js", 51 | dep: "'components' with elementName 'component-c'", 52 | }), 53 | ), 54 | type: "Literal", 55 | }, 56 | ], 57 | }, 58 | // import componentA from component-a 59 | { 60 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 61 | code: "import ComponentA from 'components/component-a/ComponentA'", 62 | options, 63 | errors: [ 64 | { 65 | message: customErrorMessage( 66 | errorMessages, 67 | 1, 68 | entryPointNoRuleMessage({ 69 | entryPoint: "ComponentA.js", 70 | dep: "'components' with elementName 'component-a'", 71 | }), 72 | ), 73 | type: "Literal", 74 | }, 75 | ], 76 | }, 77 | // import helper-b index.js 78 | { 79 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 80 | code: "import HelperA from 'helpers/helper-b'", 81 | options, 82 | errors: [ 83 | { 84 | message: customErrorMessage( 85 | errorMessages, 86 | 2, 87 | entryPointNoRuleMessage({ 88 | entryPoint: "index.js", 89 | dep: "'helpers' with elementName 'helper-b'", 90 | }), 91 | ), 92 | type: "Literal", 93 | }, 94 | ], 95 | }, 96 | // import helper-a main.js 97 | { 98 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 99 | code: "import HelperA from 'helpers/helper-a/main'", 100 | options, 101 | errors: [ 102 | { 103 | message: customErrorMessage( 104 | errorMessages, 105 | 3, 106 | entryPointNoRuleMessage({ 107 | entryPoint: "main.js", 108 | dep: "'helpers' with elementName 'helper-a'", 109 | }), 110 | ), 111 | type: "Literal", 112 | }, 113 | ], 114 | }, 115 | ], 116 | }); 117 | }; 118 | 119 | // options with capture 120 | 121 | testCapture( 122 | SETTINGS.oneLevel, 123 | [ 124 | { 125 | default: "disallow", 126 | rules: [ 127 | { 128 | target: "helpers", 129 | allow: "main.js", 130 | }, 131 | { 132 | target: [["helpers", { elementName: "*-a" }]], 133 | disallow: "*", 134 | }, 135 | { 136 | target: [["helpers", { elementName: "*-a" }]], 137 | allow: "index.*", 138 | }, 139 | { 140 | target: ["components"], 141 | allow: ["${target.elementName}.js", "${from.elementName}.js"], 142 | }, 143 | ], 144 | }, 145 | ], 146 | { 147 | 3: "The entry point 'main.js' is not allowed in elements of type 'helpers' with elementName '*-a'. Disallowed in rule 2", 148 | }, 149 | ); 150 | 151 | // Custom messages 152 | 153 | testCapture( 154 | SETTINGS.oneLevel, 155 | [ 156 | { 157 | default: "disallow", 158 | message: "Importing the file ${target.internalPath} is not allowed in ${target.type}", 159 | rules: [ 160 | { 161 | target: "helpers", 162 | allow: "main.js", 163 | }, 164 | { 165 | target: [["helpers", { elementName: "*-a" }]], 166 | disallow: "*", 167 | message: 168 | "Do not import any type of file from helpers with name *-a (importing from ${from.elementName})", 169 | }, 170 | { 171 | target: [["helpers", { elementName: "*-a" }]], 172 | allow: "index.*", 173 | }, 174 | { 175 | target: ["components"], 176 | allow: ["${target.elementName}.js", "${from.elementName}.js"], 177 | }, 178 | ], 179 | }, 180 | ], 181 | { 182 | 0: "Importing the file index.js is not allowed in components", 183 | 1: "Importing the file ComponentA.js is not allowed in components", 184 | 2: "Importing the file index.js is not allowed in helpers", 185 | 3: "Do not import any type of file from helpers with name *-a (importing from component-a)", 186 | }, 187 | ); 188 | -------------------------------------------------------------------------------- /test/rules/one-level/external-template.spec.js: -------------------------------------------------------------------------------- 1 | const { EXTERNAL: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | const { customErrorMessage, externalNoRuleMessage } = require("../../support/messages"); 4 | 5 | const rule = require(`../../../src/rules/${RULE}`); 6 | 7 | const { absoluteFilePath } = pathResolvers("one-level"); 8 | 9 | const test = (settings, options, errorMessages) => { 10 | const ruleTester = createRuleTester(settings); 11 | ruleTester.run(RULE, rule, { 12 | valid: [ 13 | // Module-a can import @module-helpers/module-a 14 | { 15 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 16 | code: "import { Icon } from '@module-helpers/module-a'", 17 | options, 18 | }, 19 | // ModuleC can import moduleC from @module-helpers/all 20 | { 21 | filename: absoluteFilePath("modules/ModuleC/ModuleC.js"), 22 | code: "import { ModuleC } from '@module-helpers/all'", 23 | options, 24 | }, 25 | ], 26 | invalid: [ 27 | // Module-a can`t import @module-helpers/module-b 28 | { 29 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 30 | code: "import ModuleBHelpers from '@module-helpers/module-b'", 31 | options, 32 | errors: [ 33 | { 34 | message: customErrorMessage( 35 | errorMessages, 36 | 0, 37 | externalNoRuleMessage({ 38 | file: "'modules' with elementName 'module-a'", 39 | dep: "@module-helpers/module-b", 40 | }), 41 | ), 42 | type: "Literal", 43 | }, 44 | ], 45 | }, 46 | // ModuleC can`t import specifier different to ModuleC from @module-helpers/all 47 | { 48 | filename: absoluteFilePath("modules/ModuleC/ModuleC.js"), 49 | code: "import { Foo } from '@module-helpers/all'", 50 | options, 51 | errors: [ 52 | { 53 | message: customErrorMessage( 54 | errorMessages, 55 | 1, 56 | externalNoRuleMessage({ 57 | file: "'modules' with elementName 'ModuleC'", 58 | dep: "@module-helpers/all", 59 | }), 60 | ), 61 | type: "Literal", 62 | }, 63 | ], 64 | }, 65 | ], 66 | }); 67 | }; 68 | 69 | // disallow-based options 70 | 71 | test( 72 | SETTINGS.oneLevel, 73 | [ 74 | { 75 | default: "disallow", 76 | rules: [ 77 | { 78 | from: [["modules", { elementName: "module-a" }]], 79 | allow: ["@module-helpers/${from.elementName}"], 80 | }, 81 | { 82 | from: [["modules", { elementName: "ModuleC" }]], 83 | allow: [["@module-helpers/all", { specifiers: ["${from.elementName}"] }]], 84 | }, 85 | ], 86 | }, 87 | ], 88 | {}, 89 | ); 90 | -------------------------------------------------------------------------------- /test/rules/one-level/invalid-settings.spec.js: -------------------------------------------------------------------------------- 1 | const { ELEMENT_TYPES: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | const { customErrorMessage, elementTypesNoRuleMessage } = require("../../support/messages"); 4 | 5 | const rule = require(`../../../src/rules/${RULE}`); 6 | 7 | const { absoluteFilePath } = pathResolvers("one-level"); 8 | 9 | const test = (settings, options, errorMessages) => { 10 | const ruleTester = createRuleTester(settings); 11 | 12 | ruleTester.run(RULE, rule, { 13 | // Everything is valid, as settings are wrong 14 | valid: [ 15 | // Helpers can't import another if everything is disallowed 16 | { 17 | filename: absoluteFilePath("helpers/helper-a/HelperA.js"), 18 | code: "import HelperB from 'helpers/helper-b'", 19 | options: [ 20 | { 21 | default: "disallow", 22 | }, 23 | ], 24 | }, 25 | // Helpers can't import another helper 26 | { 27 | filename: absoluteFilePath("helpers/helper-a/HelperA.js"), 28 | code: 'import HelperB from "helpers/helper-b"', 29 | options, 30 | }, 31 | // Helpers can't import a component: 32 | { 33 | filename: absoluteFilePath("helpers/helper-a/HelperA.js"), 34 | code: "import ComponentA from 'components/component-a'", 35 | options, 36 | }, 37 | // Helpers can't import a module: 38 | { 39 | filename: absoluteFilePath("helpers/helper-a/HelperA.js"), 40 | code: "import ModuleA from 'modules/module-a'", 41 | options, 42 | }, 43 | // Components can't import a module: 44 | { 45 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 46 | code: "import ModuleA from 'modules/module-a'", 47 | options, 48 | }, 49 | ], 50 | invalid: [ 51 | // Helpers can't import another if everything is disallowed 52 | { 53 | filename: absoluteFilePath("helpers/helper-a/HelperA.js"), 54 | code: "import HelperB from 'helpers/helper-b'", 55 | settings: SETTINGS.oneLevel, 56 | options: [ 57 | { 58 | default: "disallow", 59 | }, 60 | ], 61 | errors: [ 62 | { 63 | message: customErrorMessage( 64 | errorMessages, 65 | 0, 66 | elementTypesNoRuleMessage({ 67 | file: "'helpers' with elementName 'helper-a'", 68 | dep: "'helpers' with elementName 'helper-b'", 69 | }), 70 | ), 71 | type: "Literal", 72 | }, 73 | ], 74 | }, 75 | ], 76 | }); 77 | }; 78 | 79 | // no element settings 80 | 81 | test( 82 | { 83 | ...SETTINGS.oneLevel, 84 | "boundaries/elements": [], 85 | }, 86 | [ 87 | { 88 | default: "disallow", 89 | }, 90 | ], 91 | {}, 92 | ); 93 | 94 | // no type 95 | 96 | test( 97 | { 98 | ...SETTINGS.oneLevel, 99 | "boundaries/elements": [ 100 | { 101 | pattern: "foo/*", 102 | capture: ["elementName"], 103 | }, 104 | ], 105 | }, 106 | [], 107 | {}, 108 | ); 109 | 110 | // no valid mode 111 | 112 | test( 113 | { 114 | ...SETTINGS.oneLevel, 115 | "boundaries/elements": [ 116 | { 117 | mode: "foo", 118 | }, 119 | ], 120 | }, 121 | [], 122 | {}, 123 | ); 124 | 125 | // no valid capture 126 | 127 | test( 128 | { 129 | ...SETTINGS.oneLevel, 130 | "boundaries/elements": [ 131 | { 132 | pattern: "foo/*", 133 | capture: "foo", 134 | }, 135 | ], 136 | }, 137 | [], 138 | {}, 139 | ); 140 | 141 | // invalid dependency nodes 142 | 143 | test( 144 | { 145 | "boundaries/dependency-nodes": [ 146 | // valid 147 | "import", 148 | "export", 149 | "dynamic-import", 150 | { selector: "Selector", kind: "value" }, 151 | { selector: "Selector", kind: "type" }, 152 | // invalid 153 | "unknown-default-node", 154 | { selector: "Selector", kind: "unknown-kind" }, 155 | { selector: 0, kind: "value" }, 156 | { kind: "value" }, 157 | { unknown: "object" }, 158 | 0, // invalid type 159 | ], 160 | }, 161 | [], 162 | {}, 163 | ); 164 | 165 | // invalid dependency nodes - not an array 166 | test( 167 | { 168 | "boundaries/dependency-nodes": "invalid-value", 169 | }, 170 | [], 171 | {}, 172 | ); 173 | 174 | // invalid additional dependency nodes 175 | 176 | test( 177 | { 178 | "boundaries/additional-dependency-nodes": [ 179 | // valid 180 | { selector: "Selector", kind: "value" }, 181 | { selector: "Selector", kind: "type" }, 182 | // invalid 183 | { selector: "Selector", kind: "unknown-kind" }, 184 | { selector: 0, kind: "value" }, 185 | { kind: "value" }, 186 | { unknown: "object" }, 187 | "import", 188 | "any-string", 189 | 0, 190 | ], 191 | }, 192 | [], 193 | {}, 194 | ); 195 | 196 | // invalid additional dependency nodes - not an array 197 | test( 198 | { 199 | "boundaries/additional-dependency-nodes": "invalid-value", 200 | }, 201 | [], 202 | {}, 203 | ); 204 | -------------------------------------------------------------------------------- /test/rules/one-level/no-ignored.spec.js: -------------------------------------------------------------------------------- 1 | const { NO_IGNORED: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | 4 | const rule = require(`../../../src/rules/${RULE}`); 5 | 6 | const { absoluteFilePath, codeFilePath } = pathResolvers("one-level"); 7 | 8 | const ERROR_MESSAGE = "Importing ignored files is not allowed"; 9 | 10 | const customSettings = { 11 | ...SETTINGS.deprecated, 12 | "boundaries/ignore": [codeFilePath("components/component-b/**/*.js")], 13 | }; 14 | 15 | const test = (settings) => { 16 | const ruleTester = createRuleTester(settings); 17 | ruleTester.run(RULE, rule, { 18 | valid: [ 19 | // Non recognized types can import whatever, even when ignored 20 | { 21 | filename: absoluteFilePath("foo/index.js"), 22 | code: "import ComponentB from 'components/component-b'", 23 | settings: customSettings, 24 | }, 25 | // Ignored files can import whatever, even other ignored ones 26 | { 27 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 28 | code: "import ComponentB from 'components/component-b'", 29 | settings: { 30 | ...settings, 31 | "boundaries/ignore": [codeFilePath("components/**/*.js")], 32 | }, 33 | }, 34 | // Non ignored files can be imported 35 | { 36 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 37 | code: "import ComponentB from 'components/component-b'", 38 | }, 39 | // Non local files can be imported 40 | { 41 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 42 | code: "import React from 'react'", 43 | }, 44 | ], 45 | invalid: [ 46 | // Recognized but ignored type 47 | { 48 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 49 | code: "import ComponentB from '../component-b'", 50 | settings: customSettings, 51 | errors: [ 52 | { 53 | message: ERROR_MESSAGE, 54 | type: "Literal", 55 | }, 56 | ], 57 | }, 58 | // Recognized but ignored type with alias 59 | { 60 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 61 | code: "import ComponentB from 'components/component-b'", 62 | settings: customSettings, 63 | errors: [ 64 | { 65 | message: ERROR_MESSAGE, 66 | type: "Literal", 67 | }, 68 | ], 69 | }, 70 | ], 71 | }); 72 | }; 73 | 74 | // deprecated settings 75 | test(SETTINGS.deprecated); 76 | 77 | // new settings 78 | test(SETTINGS.oneLevel); 79 | -------------------------------------------------------------------------------- /test/rules/one-level/no-unknown-files.spec.js: -------------------------------------------------------------------------------- 1 | const { NO_UNKNOWN_FILES: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | 4 | const rule = require(`../../../src/rules/${RULE}`); 5 | 6 | const { absoluteFilePath, codeFilePath } = pathResolvers("one-level"); 7 | 8 | const FOO_CODE = "export default {}"; 9 | const ERROR_MESSAGE = "File is not of any known element type"; 10 | 11 | const test = (settings) => { 12 | const ruleTester = createRuleTester(settings); 13 | ruleTester.run(RULE, rule, { 14 | valid: [ 15 | // Components files are valid 16 | { 17 | filename: absoluteFilePath("components/component-a/index.js"), 18 | code: FOO_CODE, 19 | }, 20 | // Modules files are valid 21 | { 22 | filename: absoluteFilePath("modules/module-a/ModuleA.js"), 23 | code: FOO_CODE, 24 | }, 25 | // Helpers files are valid 26 | { 27 | filename: absoluteFilePath("helpers/helper-a/index.js"), 28 | code: FOO_CODE, 29 | }, 30 | // Helpers non existant files are valid 31 | { 32 | filename: absoluteFilePath("helpers/non-existant/index.js"), 33 | code: FOO_CODE, 34 | }, 35 | // Ignored files are valid 36 | { 37 | filename: absoluteFilePath("foo/index.js"), 38 | code: FOO_CODE, 39 | settings: { 40 | ...settings, 41 | "boundaries/ignore": [codeFilePath("foo/*.js")], 42 | }, 43 | }, 44 | ], 45 | invalid: [ 46 | // Not under type folder 47 | { 48 | filename: absoluteFilePath("foo/index.js"), 49 | code: FOO_CODE, 50 | errors: [ 51 | { 52 | message: ERROR_MESSAGE, 53 | type: "Program", 54 | }, 55 | ], 56 | }, 57 | // Not under element folder 58 | { 59 | filename: absoluteFilePath("helpers/index.js"), 60 | code: FOO_CODE, 61 | errors: [ 62 | { 63 | message: ERROR_MESSAGE, 64 | type: "Program", 65 | }, 66 | ], 67 | }, 68 | ], 69 | }); 70 | }; 71 | 72 | // deprecated settings 73 | test(SETTINGS.deprecated); 74 | 75 | // new settings 76 | test(SETTINGS.oneLevel); 77 | -------------------------------------------------------------------------------- /test/rules/one-level/no-unknown.spec.js: -------------------------------------------------------------------------------- 1 | const { NO_UNKNOWN: RULE } = require("../../../src/constants/rules"); 2 | const { SETTINGS, createRuleTester, pathResolvers } = require("../../support/helpers"); 3 | 4 | const rule = require(`../../../src/rules/${RULE}`); 5 | 6 | const { absoluteFilePath, codeFilePath } = pathResolvers("one-level"); 7 | 8 | const ERROR_MESSAGE = "Importing unknown elements is not allowed"; 9 | 10 | const test = (settings) => { 11 | const ruleTester = createRuleTester(settings); 12 | 13 | const customSettings = { 14 | ...settings, 15 | "boundaries/ignore": [codeFilePath("components/component-b/**/*.js")], 16 | }; 17 | 18 | ruleTester.run(RULE, rule, { 19 | valid: [ 20 | // Non recognized types can import whatever 21 | { 22 | filename: absoluteFilePath("foo/index.js"), 23 | code: "import Foo from './foo2/foo2'", 24 | settings: customSettings, 25 | }, 26 | // Ignored files can import not recognized files 27 | { 28 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 29 | code: "import Foo from '../../foo'", 30 | settings: { 31 | ...settings, 32 | "boundaries/ignore": [codeFilePath("components/**/*.js")], 33 | }, 34 | }, 35 | // Recognized types can be imported 36 | { 37 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 38 | code: "import ComponentB from 'components/component-b'", 39 | }, 40 | // External dependencies can be imported 41 | { 42 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 43 | code: "import 'chalk'", 44 | }, 45 | ], 46 | invalid: [ 47 | // Not recognized type 48 | { 49 | filename: absoluteFilePath("components/component-a/ComponentA.js"), 50 | code: "import Foo from '../../foo'", 51 | errors: [ 52 | { 53 | message: ERROR_MESSAGE, 54 | type: "Literal", 55 | }, 56 | ], 57 | }, 58 | ], 59 | }); 60 | }; 61 | 62 | // deprecated settings 63 | test(SETTINGS.deprecated); 64 | 65 | // new settings 66 | test(SETTINGS.oneLevel); 67 | -------------------------------------------------------------------------------- /test/src/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "jest": true, 4 | "afterEach": true, 5 | "afterAll": true, 6 | "beforeAll": true, 7 | "beforeEach": true, 8 | "describe": true, 9 | "expect": true, 10 | "it": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/src/index.spec.js: -------------------------------------------------------------------------------- 1 | const pluginPackage = require("../../src/index"); 2 | 3 | const RULES = require("../../src/constants/rules"); 4 | 5 | describe("package", () => { 6 | describe("rules property", () => { 7 | it("should contain all rules defined in constants", () => { 8 | Object.keys(RULES).forEach((ruleKey) => { 9 | expect(pluginPackage.rules[RULES[ruleKey]].create).toBeDefined(); 10 | }); 11 | }); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/support/messages.js: -------------------------------------------------------------------------------- 1 | function errorMessage(errors, index, defaultMessage) { 2 | return errors[index] || defaultMessage; 3 | } 4 | 5 | function customErrorMessage(errors, index, defaultMessage) { 6 | return errorMessage(errors, index, defaultMessage); 7 | } 8 | 9 | function elementTypesNoRuleMessage({ file, dep }) { 10 | return `No rule allowing this dependency was found. File is of type ${file}. Dependency is of type ${dep}`; 11 | } 12 | 13 | function entryPointNoRuleMessage({ entryPoint, dep }) { 14 | return `No rule allows the entry point '${entryPoint}' in dependencies of type ${dep}`; 15 | } 16 | 17 | function externalNoRuleMessage({ file, dep }) { 18 | return `No rule allows the usage of external module '${dep}' in elements of type ${file}`; 19 | } 20 | 21 | function noPrivateMessage({ dep }) { 22 | return `Dependency is private of element of type ${dep}`; 23 | } 24 | 25 | module.exports = { 26 | customErrorMessage, 27 | elementTypesNoRuleMessage, 28 | entryPointNoRuleMessage, 29 | noPrivateMessage, 30 | externalNoRuleMessage, 31 | }; 32 | --------------------------------------------------------------------------------