1 | # :file_folder: tslint-folders
|
2 |
|
3 | Use tslint to check for invalid imports between packages and folders in your TypeScript project.
|
4 |
|
5 | Automatic validation and documentation of package architecture (via `tslint-folders-diagrams`).
|
6 |
|
7 | ## status - stable
|
8 |
|
9 | tslint-folders is stable and in use every day in CI builds and on dev boxes (Linux, Mac, Windows) for at least one major product.
|
10 |
|
11 | [![Build Status](https://travis-ci.com/mrseanryan/tslint-folders.svg?branch=master)](https://travis-ci.com/mrseanryan/tslint-folders)
|
12 | [![Coveralls](https://img.shields.io/coveralls/mrseanryan/tslint-folders.svg)](https://coveralls.io/github/mrseanryan/tslint-folders)
|
13 | [![Size](https://packagephobia.now.sh/badge?p=tslint-folders)](https://packagephobia.now.sh/result?p=tslint-folders)
|
14 |
|
15 | [![Dependencies](https://david-dm.org/mrseanryan/tslint-folders.svg)](https://david-dm.org/mrseanryan/tslint-folders)
|
16 |
|
17 | [![npm Package](https://img.shields.io/npm/v/tslint-folders.svg?style=flat-square)](https://www.npmjs.org/package/tslint-folders)
|
18 | [![NPM Downloads](https://img.shields.io/npm/dm/tslint-folders.svg)](https://npmjs.org/package/tslint-folders)
|
19 |
|
20 | [![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
|
21 | [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
|
22 |
|
23 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
24 |
|
25 | ---
|
26 |
|
27 | ## why?
|
28 |
|
29 | Save time spent manually code reviewing for 'silly' mistakes such as:
|
30 |
|
31 | - Architecture violations:
|
32 | - importing from a 'higher level' package or folder
|
33 | - importing from folders in both directions
|
34 | - Importing from an 'invalid' folder like 'dist' or 'modules' (ugly, and in some cases this can cause issues like webpack bundling the same code twice)
|
35 | - Pushing code with disabled tests or with breakpoint code
|
36 | - Inconsistent naming of files (the default tslint rule `file-name-casing` only allows for 1 style)
|
37 |
|
38 | ---
|
39 |
|
40 | ## features
|
41 |
|
42 | - Uses a simple JSON file to model the desired relations between folders and sub-folders
|
43 | - Provides a custom tslint rule that walks your TypeScript project, checking for imports that violate the model
|
44 | - Other custom rules:
|
45 | - configurably detect disabled tests
|
46 | - detect debug/breakpoint code
|
47 | - detect invalid imports from folders like 'node_modules' or 'dist'
|
48 | - detect filenames that do not match expected style (allows for more than 1 filename style)
|
49 | - Provides a tool to generate architecture diagrams from the same model, via [tslint-folders-diagrams](https://github.com/mrseanryan/tslint-folders-diagrams)
|
50 |
|
51 | ---
|
52 |
|
53 | ## versioning
|
54 |
|
55 | We use [SemVer](https://semver.org) for versioning. For the versions available, see [Releases](https://github.com/mrseanryan/tslint-folders/releases).
|
56 |
|
57 | ---
|
58 |
|
59 | ## usage
|
60 |
|
61 | ### 1 Install via yarn into your website
|
62 |
|
63 | ```
|
64 | yarn add tslint-folders
|
65 | ```
|
66 |
|
67 | ### 2 Configure tslint to pick up the custom rules
|
68 |
|
69 | Edit your `tslint.json` to have an entry `"rulesDirectory"` that points to tslint-folders.
|
70 |
|
71 | Normally this would be like:
|
72 |
|
73 | ```
|
74 | "rulesDirectory": "./node_modules/tslint-folders/dist/lib/"
|
75 | ```
|
76 |
|
77 | See [tslint.tslint-folders.json](https://github.com/mrseanryan/tslint-folders/blob/master/tslint.tslint-folders.json) for an example.
|
78 |
|
79 | ### 3 Configure the rules
|
80 |
|
81 | The tslint rules are enabled and configured in `tslint.json`.
|
82 |
|
83 | See the section under `tsf-folders-imports-between-packages` in [tslint.tslint-folders.json](https://github.com/mrseanryan/tslint-folders/blob/master/tslint.tslint-folders.json) or the [unit tests](https://github.com/mrseanryan/tslint-folders/blob/master/test/rules/) for examples.
|
84 |
|
85 | Optionally, you can split out the tslint-folders configuration into a separate file, like `tslint.tslint-folders.json`. To reference the file, add this code to `tslint.json`:
|
86 |
|
87 | ```
|
88 | "extends": "./tslint.tslint-folders.json"
|
89 | ```
|
90 |
|
91 | Assuming tslint is already in place, then you should now see any unexpected imports (or disabled tests) be flagged by tslint. This should work as usual for tslint: on the command line, or in an editor such as Visual Code (may require refreshing the editor).
|
92 |
|
93 | ### 4 Generate a summary of the package configuration
|
94 |
|
95 | See [tslint-folders-diagrams](https://github.com/mrseanryan/tslint-folders-diagrams)
|
96 |
|
97 | ### using graphviz to generate image diagrams of the architecture
|
98 |
|
99 | A diagram can be automatically generated from the same config used to validated the code:
|
100 |
|
101 | ![example diagram](https://github.com/mrseanryan/tslint-folders/blob/master/static/images/example_diagram_from_Dot_output.png?raw=true)
|
102 |
|
103 | see [tslint-folders-diagrams](https://github.com/mrseanryan/tslint-folders-diagrams) for details.
|
104 |
|
105 | ---
|
106 |
|
107 | ## Summary of the Custom Rules
|
108 |
|
109 | here is a summary of the current custom rules.
|
110 |
|
111 | | Rule ID | Description |
|
112 | | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
113 | | tsf-folders-disabled-test | Detect a disabled unit test, test suite or integration test. |
|
114 | | tsf-folders-file-names | Validates casing of filenames. Similar to standard rule `file-name-casing` except it supports multiple allowed casings, and disallows file names with invalid characters (such as spaces or commas). |
|
115 | | tsf-folders-import-from-disallowed-folders | Detect an import from a non-standard folder like node_modules |
|
116 | | tsf-folders-imports-between-packages | Detect an import from a 'higher level' package: for example, import from an application 'shell' package when inside an 'area' package. This is the main custom rule. Also can detect when a package has imports using this packages name (instead of a relative path). |
|
117 | | tsf-folders-test-with-breakpoint | Detect when an integration test has a break point like `browser.debug()` |
|
118 |
|
119 | ---
|
120 |
|
121 | ## sites
|
122 |
|
123 | | site | URL |
|
124 | | -------------------- | -------------------------------------------- |
|
125 | | source code (github) | https://github.com/mrseanryan/tslint-folders |
|
126 | | github page | https://mrseanryan.github.io/tslint-folders/ |
|
127 | | npm | https://www.npmjs.com/package/tslint-folders |
|
128 |
|
129 | ---
|
130 |
|
131 | ## approach taken
|
132 |
|
133 | All of the rules use the same prefix `tsf-folders-`.
|
134 |
|
135 | To make it clear to developers that a _custom_ rule is involved, all messages from the rules also include the rule id.
|
136 |
|
137 | Some of these rules could be replaced by standard tslint configuration.
|
138 | However, having custom rules gives clearer messages to help the developer to know what to fix (or what rule to disable for that piece of code).
|
139 |
|
140 | Some of the rules are not strictly about 'folders', but are included here as they also seem useful.
|
141 |
|
142 | For more details and examples please see the [unit tests](https://github.com/mrseanryan/tslint-folders/blob/master/test/rules/)
|
143 |
|
144 | ---
|
145 |
|
146 | ## building and testing this source code
|
147 |
|
148 | To work on the source code for tslint-folders, there are a few scripts:
|
149 |
|
150 | | command | description |
|
151 | | ------------- | ----------------------------------------------------------------------- |
|
152 | | yarn build | Builds the rules to the 'dist' folder, from where they can be executed. |
|
153 | | yarn lint | Lints the source code of the rules. |
|
154 | | yarn start | Builds, tests and lints the code. |
|
155 | | yarn test | Tests the rules against spec files (\*.lint) |
|
156 | | yarn test-one | Test a single rule against spec files (\*.lint) |
|
157 |
|
158 | ---
|
159 |
|
160 | ## unit tests
|
161 |
|
162 | The unit tests for the rule `tsf-folders-imports-between-packages` are [here](https://github.com/mrseanryan/tslint-folders/blob/master/test/rules/tsf-folders-imports-between-packages).
|
163 |
|
164 | The unit tests use test data to check the package boundaries of a fairly typical website.
|
165 |
|
166 | The matching configuration can be seen in [tslint.tslint-folders.json](https://github.com/mrseanryan/tslint-folders/blob/master/tslint.tslint-folders.json)
|
167 |
|
168 | ### test data - packages
|
169 |
|
170 | The test data is based around a website that uses multiple packages:
|
171 |
|
172 | | Package name | Description |
|
173 | | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
174 | | shell | The application shell - this is the top level package, and it can import from any other package. |
|
175 | | todo-area | A 'todo app' area of the website, that is hosted within the shell. It should not import from the shell or from other 'area' packages. |
|
176 | | todo-contact | A 'contact info' area of the website, that is hosted within the shell. It should not import from the shell or from other 'area' packages. |
|
177 | | grid-package | A UI grid that is used by area packages. It should not import any other recognised packages. |
|
178 | | utils | A 'utils' package used by the shell and area packages. It should not import any other recognised packages. |
|
179 |
|
180 | **Example validation**: 'shell' should be able to import from 'todo-area', but not the other way around (shell is at a higher level of abstraction, and also want to avoid 2-way dependencies).
|
181 |
|
182 | ### test data - packages with sub-folders
|
183 |
|
184 | tslint-folders can also validate imports between sub-folders of a package.
|
185 |
|
186 | The test data 'todo-area' package is configured with fairly typical sub-folders such as 'components' and 'models'. [tslint.tslint-folders.json](https://github.com/mrseanryan/tslint-folders/blob/master/tslint.tslint-folders.json) has been configured to check the imports between these folders.
|
187 |
|
188 | | Sub-folder name | Description |
|
189 | | --------------- | --------------------------------------------------------------------------------------- |
|
190 | | components | Top-level folder of UI components. Can import from any of the other recognised folders. |
|
191 | | viewmodels | Folder of view models, used by the UI components. Can only import from models or utils. |
|
192 | | models | Folder of models, used by the view models. Can only import from utils. |
|
193 | | utils | A 'utils' folder. It should not import any other recognised folders. |
|
194 |
|
195 | **Example validation**: 'components' should be able to import from 'models', but not the other way around (components is at a higher level of abstraction, and also want to avoid 2-way dependencies).
|
196 |
|
197 | ---
|
198 |
|
199 | ## developing code in _this_ repository
|
200 |
|
201 | see the [contributing readme](CONTRIBUTING.md).
|
202 |
|
203 | ## origin
|
204 |
|
205 | This project is based on the excellent seeder project [typescript-library-starter](https://github.com/alexjoverm/typescript-library-starter).
|
206 |
|
207 | The project was started to avoid having to repeatedly fix similar coding issues in large TypeScript code bases.
|
208 |
|
209 | ### ORIGINAL readme (from the seeder project)
|
210 |
|
211 | [see here](https://github.com/mrseanryan/tslint-folders/blob/master/readme.original.md)
|
212 |
|
213 | ---
|
214 |
|
215 | ## that's it
|
216 |
|
217 | That's pretty much it. Let me know if this is useful or how it can be improved!
|
218 |
|
219 | ## authors
|
220 |
|
221 | Original work by Sean Ryan - mr.sean.ryan(at gmail.com)
|
222 |
|
223 | ## licence = MIT
|
224 |
|
225 | This project is licensed under the MIT License - see the [LICENSE](https://github.com/mrseanryan/tslint-folders/blob/master/LICENSE) file for details
|