@blumintinc/eslint-plugin-blumint 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -281
- package/lib/index.d.ts +1 -0
- package/lib/index.js +69 -0
- package/lib/rules/array-methods-this-context.d.ts +3 -0
- package/lib/rules/array-methods-this-context.js +64 -0
- package/lib/rules/class-methods-read-top-to-bottom.d.ts +2 -0
- package/lib/rules/class-methods-read-top-to-bottom.js +72 -0
- package/lib/rules/dynamic-https-errors.d.ts +2 -0
- package/lib/rules/dynamic-https-errors.js +57 -0
- package/lib/rules/export-if-in-doubt.d.ts +2 -0
- package/lib/rules/export-if-in-doubt.js +69 -0
- package/lib/rules/extract-global-constants.d.ts +2 -0
- package/lib/rules/extract-global-constants.js +63 -0
- package/lib/rules/generic-starts-with-t.d.ts +2 -0
- package/lib/rules/generic-starts-with-t.js +35 -0
- package/lib/rules/no-async-array-filter.d.ts +2 -0
- package/lib/rules/no-async-array-filter.js +40 -0
- package/lib/rules/no-async-foreach.d.ts +2 -0
- package/lib/rules/no-async-foreach.js +37 -0
- package/lib/rules/no-conditional-literals-in-jsx.d.ts +2 -0
- package/lib/rules/no-conditional-literals-in-jsx.js +61 -0
- package/lib/rules/no-filter-without-return.d.ts +2 -0
- package/lib/rules/no-filter-without-return.js +41 -0
- package/lib/rules/no-misused-switch-case.d.ts +2 -0
- package/lib/rules/no-misused-switch-case.js +35 -0
- package/lib/rules/no-unpinned-dependencies.d.ts +2 -0
- package/lib/rules/no-unpinned-dependencies.js +65 -0
- package/lib/rules/no-useless-fragment.d.ts +2 -0
- package/lib/rules/no-useless-fragment.js +46 -0
- package/lib/rules/prefer-fragment-shorthand.d.ts +3 -0
- package/lib/rules/prefer-fragment-shorthand.js +40 -0
- package/lib/rules/prefer-type-over-interface.d.ts +2 -0
- package/lib/rules/prefer-type-over-interface.js +45 -0
- package/lib/rules/require-memo.d.ts +6 -0
- package/lib/rules/require-memo.js +166 -0
- package/lib/utils/ASTHelpers.d.ts +12 -0
- package/lib/utils/ASTHelpers.js +336 -0
- package/lib/utils/createRule.d.ts +2 -0
- package/lib/utils/createRule.js +6 -0
- package/lib/utils/graph/ClassGraphBuilder.d.ts +29 -0
- package/lib/utils/graph/ClassGraphBuilder.js +80 -0
- package/lib/utils/graph/ClassGraphSorter.d.ts +7 -0
- package/lib/utils/graph/ClassGraphSorter.js +10 -0
- package/lib/utils/graph/ClassGraphSorterReadability.d.ts +16 -0
- package/lib/utils/graph/ClassGraphSorterReadability.js +94 -0
- package/lib/utils/ruleTester.d.ts +5 -0
- package/lib/utils/ruleTester.js +23 -0
- package/package.json +33 -13
- package/CHANGELOG.md +0 -63
- package/assets/logo.svg +0 -26
- package/jest.config.js +0 -13
- package/plugin/README.md +0 -80
- package/plugin/docs/rules/array-methods-this-context.md +0 -30
- package/plugin/docs/rules/class-methods-read-top-to-bottom.md +0 -46
- package/plugin/docs/rules/dynamic-https-errors.md +0 -23
- package/plugin/docs/rules/export-if-in-doubt.md +0 -26
- package/plugin/docs/rules/extract-global-constants.md +0 -33
- package/plugin/docs/rules/generic-starts-with-t.md +0 -33
- package/plugin/docs/rules/no-async-array-filter.md +0 -32
- package/plugin/docs/rules/no-async-foreach.md +0 -41
- package/plugin/docs/rules/no-conditional-literals-in-jsx.md +0 -27
- package/plugin/docs/rules/no-filter-without-return.md +0 -43
- package/plugin/docs/rules/no-misused-switch-case.md +0 -38
- package/plugin/docs/rules/no-unpinned-dependencies.md +0 -34
- package/plugin/docs/rules/no-useless-fragment.md +0 -25
- package/plugin/docs/rules/prefer-fragment-shorthand.md +0 -25
- package/plugin/docs/rules/prefer-type-over-interface.md +0 -25
- package/plugin/docs/rules/require-memo.md +0 -36
- package/plugin/package-lock.json +0 -7662
- package/plugin/package.json +0 -45
- package/tsconfig.json +0 -79
package/README.md
CHANGED
|
@@ -1,299 +1,80 @@
|
|
|
1
|
-
|
|
1
|
+
# @blumintinc/eslint-plugin-blumint
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Custom eslint rules for use at BluMint
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
<br />
|
|
7
|
-
<p align="center">
|
|
8
|
-
<!---TODO: Update below with repository URL -->
|
|
9
|
-
<a href="https://github.com/BluMintInc/template-gitpod">
|
|
10
|
-
<img src="assets/logo.svg" alt="Logo" height=100>
|
|
11
|
-
</a>
|
|
12
|
-
<p align="center">
|
|
13
|
-
<!---TODO: Update below with repository name -->
|
|
14
|
-
TEMPLATE
|
|
15
|
-
<br />
|
|
16
|
-
<!---TODO: Update below with repository URL -->
|
|
17
|
-
<a href="https://github.com/BluMintInc/template-gitpod/issues">Report Bug</a>
|
|
18
|
-
·
|
|
19
|
-
<!---TODO: Update below with repository URL -->
|
|
20
|
-
<a href="https://github.com/BluMintInc/template-gitpod/issues">Request Feature</a>
|
|
21
|
-
</p>
|
|
22
|
-
</p>
|
|
23
|
-
<br />
|
|
5
|
+
## Installation
|
|
24
6
|
|
|
25
|
-
|
|
7
|
+
You'll first need to install [ESLint](https://eslint.org/):
|
|
26
8
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- [Environment Dependencies](#environment-dependencies)
|
|
30
|
-
- [Recommended Browser Extensions](#recommended-browser-extensions)
|
|
31
|
-
- [Getting Started](#getting-started)
|
|
32
|
-
- [Zero-Installation Development](#zero-installation-development)
|
|
33
|
-
- [Docker Installation](#docker-installation)
|
|
34
|
-
- [Contributing](#contributing)
|
|
35
|
-
- [Agile Development](#agile-development)
|
|
36
|
-
- [Testing](#testing)
|
|
37
|
-
- [Gitflow](#gitflow)
|
|
38
|
-
- [Commitizen](#commitizen)
|
|
39
|
-
- [Diagramming](#diagramming)
|
|
40
|
-
- [Workflow Automation](#workflow-automation)
|
|
41
|
-
- [CI](#ci)
|
|
42
|
-
- [CD](#cd)
|
|
43
|
-
- [Dependency Management](#dependency-management)
|
|
44
|
-
- [Static Code Analysis](#static-code-analysis)
|
|
45
|
-
- [License](#license)
|
|
46
|
-
|
|
47
|
-
<br />
|
|
48
|
-
|
|
49
|
-
## About this Project
|
|
50
|
-
|
|
51
|
-
This repository is a template repository for Gitpod-based development of a service.
|
|
52
|
-
|
|
53
|
-
### Built with
|
|
54
|
-
|
|
55
|
-
- [Typescript](https://www.typescriptlang.org/)
|
|
56
|
-
- [Jest](https://mochajs.org/)
|
|
57
|
-
|
|
58
|
-
### Environment Dependencies
|
|
59
|
-
|
|
60
|
-
- [NodeJS](https://nodejs.org) (16 with npm ^8.16.0)
|
|
61
|
-
|
|
62
|
-
### Recommended Browser Extensions
|
|
63
|
-
|
|
64
|
-
It is recommended that you install the following browser extensions for the best experience
|
|
65
|
-
interacting with this repository:
|
|
66
|
-
|
|
67
|
-
1. [Gitpod Browser Extension](https://www.gitpod.io/docs/browser-extension/)
|
|
68
|
-
|
|
69
|
-
<br />
|
|
70
|
-
|
|
71
|
-
## Getting Started
|
|
72
|
-
|
|
73
|
-
### Zero-Installation Development
|
|
74
|
-
|
|
75
|
-
<!---TODO: Update below with repository URL -->
|
|
76
|
-
|
|
77
|
-
[](https://gitpod.io/#https://github.com/BluMintInc/template-gitpod)
|
|
78
|
-
|
|
79
|
-
It is highly recommended to conduct development of this repository
|
|
80
|
-
via [Gitpod's online IDE](https://www.gitpod.io/docs/ide/). Click the following to
|
|
81
|
-
get started with zero installation requirements:
|
|
82
|
-
|
|
83
|
-
<p>
|
|
84
|
-
<!---TODO: Update below with repository URL -->
|
|
85
|
-
<a href="https://gitpod.io/#https://github.com/BluMintInc/template-gitpod" target="_blank" rel="nofollow noopener noreferrer">
|
|
86
|
-
<img src="https://gitpod.io/button/open-in-gitpod.svg" alt="Open in Gitpod">
|
|
87
|
-
</a>
|
|
88
|
-
</p>
|
|
89
|
-
|
|
90
|
-
Gitpod is a one-click online IDE for Cloud-based development. The following video
|
|
91
|
-
provides a very effective introduction to Gitpod: [https://www.youtube.com/watch?v=qLv6-Uop0yc](https://www.youtube.com/watch?v=qLv6-Uop0yc).
|
|
92
|
-
|
|
93
|
-
<br />
|
|
94
|
-
|
|
95
|
-
### Docker Installation
|
|
96
|
-
|
|
97
|
-
Alternatively, this repo supports [VS Code Remote Container Development](https://code.visualstudio.com/docs/remote/containers#_quick-start-open-a-git-repository-or-github-pr-in-an-isolated-container-volume) for Dockerized development inside VSCode.
|
|
98
|
-
|
|
99
|
-
**Step #1**: To get started, first make sure to install the followin prerequisites:
|
|
100
|
-
|
|
101
|
-
1. Visual Studio Code
|
|
102
|
-
|
|
103
|
-
- Manual installation: https://code.visualstudio.com/download
|
|
104
|
-
- Windows (via [Chocolately](https://chocolatey.org/)):
|
|
105
|
-
```bash
|
|
106
|
-
choco install vscode
|
|
107
|
-
```
|
|
108
|
-
- Mac or Linux (via [Homebrew](https://brew.sh/)):
|
|
109
|
-
```sh
|
|
110
|
-
brew update
|
|
111
|
-
brew tap homebrew/cask-cask
|
|
112
|
-
brew cask search visual-studio-code
|
|
113
|
-
brew cask install visual-studio-code
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
2. [Visual Studio Code Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)
|
|
117
|
-
extension pack, which can be installed into VS Code with [this manual installation link](vscode:extension/ms-vscode-remote.vscode-remote-extensionpack).
|
|
118
|
-
|
|
119
|
-
3. [Docker Desktop](https://www.docker.com/products/docker-desktop)
|
|
120
|
-
- Manual installation: https://www.docker.com/products/docker-desktop for Widows / Mac
|
|
121
|
-
- Windows (via [Chocolately](https://chocolatey.org/)):
|
|
122
|
-
```bash
|
|
123
|
-
choco install docker-desktop
|
|
124
|
-
```
|
|
125
|
-
and follow
|
|
126
|
-
- Mac or Linux (via [Homebrew](https://brew.sh/)):
|
|
127
|
-
```sh
|
|
128
|
-
brew cask install docker
|
|
129
|
-
```
|
|
130
|
-
- Linux (Ubuntu, Debian):
|
|
131
|
-
```sh
|
|
132
|
-
sudo apt-get update
|
|
133
|
-
sudo apt-get remove docker docker-engine docker.io
|
|
134
|
-
sudo apt install docker.io
|
|
135
|
-
sudo systemctl start docker
|
|
136
|
-
sudo systemctl enable docker
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
**Step #2**: Start the Docker daemon if it has already not started automatially after the
|
|
140
|
-
installation finishes (run the Docker Desktop application). To ensure docker is running,
|
|
141
|
-
attempt the following commands:
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
docker version
|
|
145
|
-
docker run hello-world
|
|
9
|
+
```sh
|
|
10
|
+
npm i eslint --save-dev
|
|
146
11
|
```
|
|
147
12
|
|
|
148
|
-
|
|
149
|
-
**Remote-Containers: Clone Repository in Container Volume..** from the Command Palette.
|
|
150
|
-
|
|
151
|
-
<!---TODO: Update below with repository URL -->
|
|
152
|
-
|
|
153
|
-
**Step #4**: Enter this repository's Git URI: https://github.com/BluMintInc/template-gitpod.git.
|
|
154
|
-
VS Code will install all required dependencies and set up the environment from the Dockerfile configuration.
|
|
13
|
+
Next, install `@blumintinc/eslint-plugin-blumint`:
|
|
155
14
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
### [Agile Development](https://agilemanifesto.org/)
|
|
161
|
-
|
|
162
|
-
We are uncovering better ways of developing
|
|
163
|
-
software by doing it and helping others do it.
|
|
164
|
-
|
|
165
|
-
Through this work we have come to value:
|
|
166
|
-
|
|
167
|
-
- **Individuals and interactions** over _processes and tools_
|
|
168
|
-
- **Working software** over _comprehensive documentation_
|
|
169
|
-
- **Customer collaboration** over _contract negotiation_
|
|
170
|
-
- **Responding to change** over _following a plan_
|
|
171
|
-
|
|
172
|
-
That is, while there is value in the items on
|
|
173
|
-
_the right_, we value the items **on the left** more.
|
|
174
|
-
|
|
175
|
-
Furthermore, we value these principles:
|
|
176
|
-
|
|
177
|
-
1. Our highest priority is to satisfy the customer
|
|
178
|
-
through early and continuous delivery
|
|
179
|
-
of valuable software.
|
|
180
|
-
2. Welcome changing requirements, even late in
|
|
181
|
-
development. Agile processes harness change for
|
|
182
|
-
the customer's competitive advantage.
|
|
183
|
-
3. Deliver working software frequently, from a
|
|
184
|
-
couple of weeks to a couple of months, with a
|
|
185
|
-
preference to the shorter timescale.
|
|
186
|
-
4. Business people and developers must work
|
|
187
|
-
together daily throughout the project.
|
|
188
|
-
5. Build projects around motivated individuals.
|
|
189
|
-
Give them the environment and support they need,
|
|
190
|
-
and trust them to get the job done.
|
|
191
|
-
6. The most efficient and effective method of
|
|
192
|
-
conveying information to and within a development
|
|
193
|
-
team is face-to-face conversation.
|
|
194
|
-
7. Working software is the primary measure of progress.
|
|
195
|
-
8. Agile processes promote sustainable development.
|
|
196
|
-
The sponsors, developers, and users should be able
|
|
197
|
-
to maintain a constant pace indefinitely.
|
|
198
|
-
9. Continuous attention to technical excellence
|
|
199
|
-
and good design enhances agility.
|
|
200
|
-
10. Simplicity--the art of maximizing the amount
|
|
201
|
-
of work not done--is essential.
|
|
202
|
-
11. The best architectures, requirements, and designs
|
|
203
|
-
emerge from self-organizing teams.
|
|
204
|
-
12. At regular intervals, the team reflects on how
|
|
205
|
-
to become more effective, then tunes and adjusts
|
|
206
|
-
its behavior accordingly.
|
|
207
|
-
|
|
208
|
-
### Testing
|
|
209
|
-
|
|
210
|
-
Each contributor to this repository is obligated to provide sufficient test coverage over their contributions.
|
|
211
|
-
We use the [Jest](https://jestjs.io/) test framework.
|
|
212
|
-
|
|
213
|
-
### [Gitflow](https://nvie.com/posts/a-successful-git-branching-model/)
|
|
214
|
-
|
|
215
|
-
Version control with git on this repo is in strict adherence to
|
|
216
|
-
the [Gitflow Workflow](https://nvie.com/posts/a-successful-git-branching-model/).
|
|
217
|
-
Gitflow was architectured by Vincent Driesssen in 2010 and since has been adopted with massive
|
|
218
|
-
popularity as a very effective development workflow under distributed version control.
|
|
219
|
-
|
|
220
|
-
This project makes use of the [git-flow](https://github.com/nvie/gitflow) integration setup in
|
|
221
|
-
the Docker container, which lets you execute `git flow` commands on the terminal rather than
|
|
222
|
-
`git` commands directly.
|
|
223
|
-
|
|
224
|
-
The project also utilizes [githooks](https://git-scm.com/docs/githooks/en) to enforce gitflow and
|
|
225
|
-
prevent users from accidently pushing to the main branch.
|
|
226
|
-
|
|
227
|
-
Plase read the following article for a sufficient introduction to the Gitflow
|
|
228
|
-
Workflow: https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow.
|
|
229
|
-
|
|
230
|
-
### [Commitizen](https://commitizen-tools.github.io/commitizen/)
|
|
231
|
-
|
|
232
|
-
This project uses [githooks](https://git-scm.com/docs/githooks/en) to enforce standarized commits
|
|
233
|
-
according to the [Commitizen](https://commitizen-tools.github.io/commitizen/) style. Running
|
|
234
|
-
`git commit` on the command line instigates a series of prompts guiding you through the standard.
|
|
235
|
-
|
|
236
|
-
### Diagramming
|
|
237
|
-
|
|
238
|
-
All diagrams should be included on the repository to which they pertain. We use
|
|
239
|
-
[PlantUML](https://plantuml.com/) to build all of our diagrams. PlantUML has a Domain Specific
|
|
240
|
-
Language (DSL) for declaratively building [various types of diagrams](https://plantuml.com/).
|
|
241
|
-
You can write a .wsd, .pu, .puml, .plantuml, or .iuml file containing PlantUML DSL and the
|
|
242
|
-
[PlantUML Extension](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml)
|
|
243
|
-
will enable you to render that diagram in a live preview by pressing Alt + D.
|
|
244
|
-
|
|
245
|
-
<br />
|
|
246
|
-
<br />
|
|
247
|
-
|
|
248
|
-
## Workflow Automation
|
|
249
|
-
|
|
250
|
-
This repository uses [Github Actions](https://docs.github.com/en/actions) for several workflow
|
|
251
|
-
automations as well as several organizational [Github Integrations](https://github.com/integrations).
|
|
252
|
-
|
|
253
|
-
### CI
|
|
254
|
-
|
|
255
|
-
Pre-commit [githooks](https://git-scm.com/docs/githooks/en) lint the codebase and then run all the
|
|
256
|
-
project's [Jest](https://jestjs.io/) tests to prevent regressions from even being checked into
|
|
257
|
-
the codebase. On top of this, the
|
|
258
|
-
[Test](https://github.com/BluMintInc/template-gitpod/blob/master/.github/workflows/test-report.yml)
|
|
259
|
-
Action runs the project's [Jest](https://jestjs.io/) tests to check PRs before they are merged.
|
|
260
|
-
|
|
261
|
-
### CD
|
|
262
|
-
<!---TODO: Update below paragraph with repository URLs -->
|
|
263
|
-
The [Release](https://github.com/BluMintInc/template-gitpod/blob/master/.github/workflows/semantic-release.yml)
|
|
264
|
-
Action triggers on commits to the main branch utilzing the repository's
|
|
265
|
-
[Commitizen](https://commitizen-tools.github.io/commitizen/) commit style to automatically version published
|
|
266
|
-
code according to [SemVar](https://semver.org/). The
|
|
267
|
-
[Release](https://github.com/BluMintInc/template-gitpod/blob/master/.github/workflows/semantic-release.yml)
|
|
268
|
-
Action also publishes the project to our private npmjs repository scoped under [@blumint](https://www.npmjs.com/settings/minimap-inc/packages).
|
|
15
|
+
```sh
|
|
16
|
+
npm install @blumintinc/eslint-plugin-blumint --save-dev
|
|
17
|
+
```
|
|
269
18
|
|
|
270
|
-
|
|
271
|
-
vet and squash the commits of merged PRs onto the main branch. For more information, see
|
|
272
|
-
[Semantic Release](https://github.com/semantic-release/semantic-release).
|
|
19
|
+
## Usage
|
|
273
20
|
|
|
274
|
-
|
|
21
|
+
Add `@blumintinc/blumint` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:
|
|
275
22
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"plugins": [
|
|
26
|
+
"@blumintinc/blumint"
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
```
|
|
279
30
|
|
|
280
|
-
### Static Code Analysis
|
|
281
31
|
|
|
282
|
-
|
|
283
|
-
vulnerabilities with the use of Cloud infrastructure (AWS, GCP, etc.) and makes PRs to corrct any detected
|
|
284
|
-
issues before they become a problem.
|
|
32
|
+
Then configure the rules you want to use under the rules section.
|
|
285
33
|
|
|
286
|
-
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"rules": {
|
|
37
|
+
"blumint/rule-name": "error"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
287
41
|
|
|
288
|
-
|
|
289
|
-
<br />
|
|
42
|
+
Or use the recommended config:
|
|
290
43
|
|
|
291
|
-
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"extends": ["some-other-plugin", "plugin:@blumintinc/blumint/recommended"]
|
|
47
|
+
}
|
|
48
|
+
```
|
|
292
49
|
|
|
293
|
-
|
|
50
|
+
## Rules
|
|
51
|
+
|
|
52
|
+
<!-- begin auto-generated rules list -->
|
|
53
|
+
|
|
54
|
+
💼 Configurations enabled in.\
|
|
55
|
+
⚠️ Configurations set to warn in.\
|
|
56
|
+
✅ Set in the `recommended` configuration.\
|
|
57
|
+
🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).
|
|
58
|
+
|
|
59
|
+
| Name | Description | 💼 | ⚠️ | 🔧 |
|
|
60
|
+
| :--------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------- | :- | :- | :- |
|
|
61
|
+
| [array-methods-this-context](docs/rules/array-methods-this-context.md) | Prevent misuse of Array methods in OOP | | ✅ | |
|
|
62
|
+
| [class-methods-read-top-to-bottom](docs/rules/class-methods-read-top-to-bottom.md) | Ensures classes read linearly from top to bottom. | | ✅ | 🔧 |
|
|
63
|
+
| [dynamic-https-errors](docs/rules/dynamic-https-errors.md) | Dynamic error details should only be in the third argument of the HttpsError constructor. The second argument is hashed to produce a unique id. | | ✅ | |
|
|
64
|
+
| [export-if-in-doubt](docs/rules/export-if-in-doubt.md) | All top-level const definitions, type definitions, and functions should be exported | | | |
|
|
65
|
+
| [extract-global-constants](docs/rules/extract-global-constants.md) | Extract constants/functions to the global scope when possible | | | |
|
|
66
|
+
| [generic-starts-with-t](docs/rules/generic-starts-with-t.md) | Enforce TypeScript generic types to start with T | | ✅ | |
|
|
67
|
+
| [no-async-array-filter](docs/rules/no-async-array-filter.md) | Disallow async callbacks for Array.filter | ✅ | | |
|
|
68
|
+
| [no-async-foreach](docs/rules/no-async-foreach.md) | Disallow Array.forEach with an async callback function | ✅ | | |
|
|
69
|
+
| [no-conditional-literals-in-jsx](docs/rules/no-conditional-literals-in-jsx.md) | Disallow use of conditional literals in JSX code | ✅ | | |
|
|
70
|
+
| [no-filter-without-return](docs/rules/no-filter-without-return.md) | Disallow Array.filter callbacks without an explicit return (if part of a block statement) | ✅ | | |
|
|
71
|
+
| [no-misused-switch-case](docs/rules/no-misused-switch-case.md) | Prevent misuse of logical OR in switch case statements | ✅ | | |
|
|
72
|
+
| [no-unpinned-dependencies](docs/rules/no-unpinned-dependencies.md) | Enforces pinned dependencies | ✅ | | 🔧 |
|
|
73
|
+
| [no-useless-fragment](docs/rules/no-useless-fragment.md) | Prevent unnecessary use of React fragments | | ✅ | 🔧 |
|
|
74
|
+
| [prefer-fragment-shorthand](docs/rules/prefer-fragment-shorthand.md) | Prefer <> shorthand for <React.Fragment> | | ✅ | 🔧 |
|
|
75
|
+
| [prefer-type-over-interface](docs/rules/prefer-type-over-interface.md) | Prefer using type alias over interface | | ✅ | 🔧 |
|
|
76
|
+
| [require-memo](docs/rules/require-memo.md) | React components must be memoized | ✅ | | 🔧 |
|
|
77
|
+
|
|
78
|
+
<!-- end auto-generated rules list -->
|
|
294
79
|
|
|
295
|
-
<!-- Markdown links & images -->
|
|
296
80
|
|
|
297
|
-
[gitpod-shield]: https://img.shields.io/badge/setup-automated-blue?logo=gitpod
|
|
298
|
-
<!---TODO: Update below with repository URL -->
|
|
299
|
-
[gitpod-url]: https://gitpod.io/#https://github.com/BluMintInc/template-gitpod
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const array_methods_this_context_1 = require("./rules/array-methods-this-context");
|
|
4
|
+
const class_methods_read_top_to_bottom_1 = require("./rules/class-methods-read-top-to-bottom");
|
|
5
|
+
const dynamic_https_errors_1 = require("./rules/dynamic-https-errors");
|
|
6
|
+
const export_if_in_doubt_1 = require("./rules/export-if-in-doubt");
|
|
7
|
+
const extract_global_constants_1 = require("./rules/extract-global-constants");
|
|
8
|
+
const generic_starts_with_t_1 = require("./rules/generic-starts-with-t");
|
|
9
|
+
const no_async_array_filter_1 = require("./rules/no-async-array-filter");
|
|
10
|
+
const no_async_foreach_1 = require("./rules/no-async-foreach");
|
|
11
|
+
const no_conditional_literals_in_jsx_1 = require("./rules/no-conditional-literals-in-jsx");
|
|
12
|
+
const no_filter_without_return_1 = require("./rules/no-filter-without-return");
|
|
13
|
+
const no_misused_switch_case_1 = require("./rules/no-misused-switch-case");
|
|
14
|
+
const no_unpinned_dependencies_1 = require("./rules/no-unpinned-dependencies");
|
|
15
|
+
const no_useless_fragment_1 = require("./rules/no-useless-fragment");
|
|
16
|
+
const prefer_fragment_shorthand_1 = require("./rules/prefer-fragment-shorthand");
|
|
17
|
+
const prefer_type_over_interface_1 = require("./rules/prefer-type-over-interface");
|
|
18
|
+
const require_memo_1 = require("./rules/require-memo");
|
|
19
|
+
module.exports = {
|
|
20
|
+
meta: {
|
|
21
|
+
name: '@blumintinc/eslint-plugin-blumint',
|
|
22
|
+
version: '1.0.3',
|
|
23
|
+
},
|
|
24
|
+
parseOptions: {
|
|
25
|
+
ecmaVersion: 2020,
|
|
26
|
+
},
|
|
27
|
+
configs: {
|
|
28
|
+
recommended: {
|
|
29
|
+
plugins: ['@blumintinc/blumint'],
|
|
30
|
+
rules: {
|
|
31
|
+
'@blumintinc/blumint/array-methods-this-context': 'warn',
|
|
32
|
+
'@blumintinc/blumint/class-methods-read-top-to-bottom': 'warn',
|
|
33
|
+
'@blumintinc/blumint/dynamic-https-errors': 'warn',
|
|
34
|
+
// '@blumintinc/blumint/export-if-in-doubt': 'warn',
|
|
35
|
+
// '@blumintinc/blumint/extract-global-constants': 'warn',
|
|
36
|
+
'@blumintinc/blumint/generic-starts-with-t': 'warn',
|
|
37
|
+
'@blumintinc/blumint/no-async-array-filter': 'error',
|
|
38
|
+
'@blumintinc/blumint/no-async-foreach': 'error',
|
|
39
|
+
'@blumintinc/blumint/no-conditional-literals-in-jsx': 'error',
|
|
40
|
+
'@blumintinc/blumint/no-filter-without-return': 'error',
|
|
41
|
+
'@blumintinc/blumint/no-misused-switch-case': 'error',
|
|
42
|
+
'@blumintinc/blumint/no-unpinned-dependencies': 'error',
|
|
43
|
+
'@blumintinc/blumint/no-useless-fragment': 'warn',
|
|
44
|
+
'@blumintinc/blumint/prefer-fragment-shorthand': 'warn',
|
|
45
|
+
'@blumintinc/blumint/prefer-type-over-interface': 'warn',
|
|
46
|
+
'@blumintinc/blumint/require-memo': 'error',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
rules: {
|
|
51
|
+
'array-methods-this-context': array_methods_this_context_1.arrayMethodsThisContext,
|
|
52
|
+
'class-methods-read-top-to-bottom': class_methods_read_top_to_bottom_1.classMethodsReadTopToBottom,
|
|
53
|
+
'dynamic-https-errors': dynamic_https_errors_1.dynamicHttpsErrors,
|
|
54
|
+
'export-if-in-doubt': export_if_in_doubt_1.exportIfInDoubt,
|
|
55
|
+
'extract-global-constants': extract_global_constants_1.extractGlobalConstants,
|
|
56
|
+
'generic-starts-with-t': generic_starts_with_t_1.genericStartsWithT,
|
|
57
|
+
'no-async-array-filter': no_async_array_filter_1.noAsyncArrayFilter,
|
|
58
|
+
'no-async-foreach': no_async_foreach_1.noAsyncForEach,
|
|
59
|
+
'no-conditional-literals-in-jsx': no_conditional_literals_in_jsx_1.noConditionalLiteralsInJsx,
|
|
60
|
+
'no-filter-without-return': no_filter_without_return_1.noFilterWithoutReturn,
|
|
61
|
+
'no-misused-switch-case': no_misused_switch_case_1.noMisusedSwitchCase,
|
|
62
|
+
'no-unpinned-dependencies': no_unpinned_dependencies_1.noUnpinnedDependencies,
|
|
63
|
+
'no-useless-fragment': no_useless_fragment_1.noUselessFragment,
|
|
64
|
+
'prefer-fragment-shorthand': prefer_fragment_shorthand_1.preferFragmentShorthand,
|
|
65
|
+
'prefer-type-over-interface': prefer_type_over_interface_1.preferTypeOverInterface,
|
|
66
|
+
'require-memo': require_memo_1.requireMemo,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.arrayMethodsThisContext = exports.ARRAY_METHODS = void 0;
|
|
4
|
+
const createRule_1 = require("../utils/createRule");
|
|
5
|
+
exports.ARRAY_METHODS = [
|
|
6
|
+
'map',
|
|
7
|
+
'filter',
|
|
8
|
+
'forEach',
|
|
9
|
+
'reduce',
|
|
10
|
+
'some',
|
|
11
|
+
'every',
|
|
12
|
+
];
|
|
13
|
+
exports.arrayMethodsThisContext = (0, createRule_1.createRule)({
|
|
14
|
+
create(context) {
|
|
15
|
+
return {
|
|
16
|
+
CallExpression(node) {
|
|
17
|
+
// Array method called with a class method reference
|
|
18
|
+
if (node.callee.type === 'MemberExpression' &&
|
|
19
|
+
node.callee.property.type === 'Identifier' &&
|
|
20
|
+
exports.ARRAY_METHODS.includes(node.callee.property.name) &&
|
|
21
|
+
node.arguments.length > 0 &&
|
|
22
|
+
node.arguments[0].type === 'MemberExpression' &&
|
|
23
|
+
node.arguments[0].object.type === 'ThisExpression') {
|
|
24
|
+
context.report({
|
|
25
|
+
node: node.arguments[0],
|
|
26
|
+
messageId: 'unexpected',
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
// Function expression bound to `this` in array method
|
|
30
|
+
else if (node.callee.type === 'MemberExpression' &&
|
|
31
|
+
node.callee.property.type === 'Identifier' &&
|
|
32
|
+
exports.ARRAY_METHODS.includes(node.callee.property.name) &&
|
|
33
|
+
node.arguments.length > 0 &&
|
|
34
|
+
node.arguments[0].type === 'CallExpression' &&
|
|
35
|
+
node.arguments[0].callee.type === 'MemberExpression' &&
|
|
36
|
+
node.arguments[0].callee.object.type === 'FunctionExpression' &&
|
|
37
|
+
node.arguments[0].callee.property.type === 'Identifier' &&
|
|
38
|
+
node.arguments[0].callee.property.name === 'bind' &&
|
|
39
|
+
node.arguments[0].arguments.length > 0 &&
|
|
40
|
+
node.arguments[0].arguments[0].type === 'ThisExpression') {
|
|
41
|
+
context.report({
|
|
42
|
+
node: node.arguments[0],
|
|
43
|
+
messageId: 'preferArrow',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
name: 'array-methods-this-context',
|
|
50
|
+
meta: {
|
|
51
|
+
type: 'problem',
|
|
52
|
+
docs: {
|
|
53
|
+
description: 'Prevent misuse of Array methods in OOP',
|
|
54
|
+
recommended: 'error',
|
|
55
|
+
},
|
|
56
|
+
schema: [],
|
|
57
|
+
messages: {
|
|
58
|
+
unexpected: 'Use an arrow function to preserve "this" context.',
|
|
59
|
+
preferArrow: 'Use an arrow function instead of binding this.',
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
defaultOptions: [],
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=array-methods-this-context.js.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.classMethodsReadTopToBottom = void 0;
|
|
4
|
+
const createRule_1 = require("../utils/createRule");
|
|
5
|
+
const ClassGraphBuilder_1 = require("../utils/graph/ClassGraphBuilder");
|
|
6
|
+
function getMemberName(member) {
|
|
7
|
+
if (member.type === 'MethodDefinition' ||
|
|
8
|
+
member.type === 'PropertyDefinition') {
|
|
9
|
+
return member.key.type === 'Identifier' ? member.key.name : null;
|
|
10
|
+
}
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
exports.classMethodsReadTopToBottom = (0, createRule_1.createRule)({
|
|
14
|
+
name: 'class-methods-read-top-to-bottom',
|
|
15
|
+
meta: {
|
|
16
|
+
type: 'suggestion',
|
|
17
|
+
docs: {
|
|
18
|
+
description: 'Ensures classes read linearly from top to bottom.',
|
|
19
|
+
recommended: 'warn',
|
|
20
|
+
},
|
|
21
|
+
schema: [],
|
|
22
|
+
messages: {
|
|
23
|
+
classMethodsReadTopToBottom: 'Methods should be ordered for top-down readability.',
|
|
24
|
+
},
|
|
25
|
+
fixable: 'code', // To allow ESLint to autofix issues.
|
|
26
|
+
},
|
|
27
|
+
defaultOptions: [],
|
|
28
|
+
create(context) {
|
|
29
|
+
let className;
|
|
30
|
+
return {
|
|
31
|
+
ClassDeclaration(node) {
|
|
32
|
+
className = node.id?.name || '';
|
|
33
|
+
},
|
|
34
|
+
'ClassBody:exit'(node) {
|
|
35
|
+
const graphBuilder = new ClassGraphBuilder_1.ClassGraphBuilder(className, node);
|
|
36
|
+
const sortedOrder = graphBuilder.memberNamesSorted;
|
|
37
|
+
const actualOrder = node.body
|
|
38
|
+
.map((member) => member.type === 'MethodDefinition' ||
|
|
39
|
+
member.type === 'PropertyDefinition'
|
|
40
|
+
? member.key.name
|
|
41
|
+
: null)
|
|
42
|
+
.filter(Boolean);
|
|
43
|
+
for (let i = 0; i < actualOrder.length; i++) {
|
|
44
|
+
if (actualOrder[i] !== sortedOrder[i]) {
|
|
45
|
+
const sourceCode = context.getSourceCode();
|
|
46
|
+
const newClassBody = sortedOrder
|
|
47
|
+
.map((n) => {
|
|
48
|
+
// Fetch the actual AST node corresponding to the name
|
|
49
|
+
const memberNode = node.body.find((member) => getMemberName(member) === n);
|
|
50
|
+
const comments = sourceCode.getCommentsBefore(memberNode);
|
|
51
|
+
memberNode.range = [
|
|
52
|
+
Math.min(memberNode.range[0], Math.min(...comments.map((comment) => comment.range[0]))),
|
|
53
|
+
Math.max(memberNode.range[1], Math.max(...comments.map((comment) => comment.range[1]))),
|
|
54
|
+
];
|
|
55
|
+
return sourceCode.getText(memberNode);
|
|
56
|
+
})
|
|
57
|
+
.join('\n');
|
|
58
|
+
return context.report({
|
|
59
|
+
node,
|
|
60
|
+
messageId: 'classMethodsReadTopToBottom',
|
|
61
|
+
fix(fixer) {
|
|
62
|
+
return fixer.replaceTextRange([node.range[0] + 1, node.range[1] - 1], // Exclude the curly braces
|
|
63
|
+
newClassBody);
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=class-methods-read-top-to-bottom.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dynamicHttpsErrors = void 0;
|
|
4
|
+
/* eslint-disable @blumintinc/blumint/extract-global-constants */
|
|
5
|
+
const createRule_1 = require("../utils/createRule");
|
|
6
|
+
const isHttpsErrorCall = (callee) => {
|
|
7
|
+
if (callee.type === 'MemberExpression') {
|
|
8
|
+
return (callee.object.type === 'Identifier' &&
|
|
9
|
+
callee.object.name === 'https' &&
|
|
10
|
+
callee.property.type === 'Identifier' &&
|
|
11
|
+
callee.property.name === 'HttpsError');
|
|
12
|
+
}
|
|
13
|
+
else if (callee.type === 'Identifier') {
|
|
14
|
+
return callee.name === 'HttpsError';
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
};
|
|
18
|
+
exports.dynamicHttpsErrors = (0, createRule_1.createRule)({
|
|
19
|
+
name: 'dynamic-https-errors',
|
|
20
|
+
meta: {
|
|
21
|
+
type: 'suggestion',
|
|
22
|
+
docs: {
|
|
23
|
+
description: 'Dynamic error details should only be in the third argument of the HttpsError constructor. The second argument is hashed to produce a unique id.',
|
|
24
|
+
recommended: 'warn',
|
|
25
|
+
},
|
|
26
|
+
schema: [],
|
|
27
|
+
messages: {
|
|
28
|
+
dynamicHttpsErrors: 'Found dynamic error details in the second argument of the HttpsError constructor - the "message" field. This field is hashed to produce a unique id for error monitoring. Move any dynamic details to the third argument - the "details" field - to preserve the unique id and to monitor the error correctly.',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
defaultOptions: [],
|
|
32
|
+
create(context) {
|
|
33
|
+
const checkForHttpsError = (node) => {
|
|
34
|
+
const callee = node.callee;
|
|
35
|
+
if (isHttpsErrorCall(callee)) {
|
|
36
|
+
const secondArg = node.arguments[1];
|
|
37
|
+
if (secondArg && secondArg.type === 'TemplateLiteral') {
|
|
38
|
+
if (secondArg.expressions.length > 0) {
|
|
39
|
+
context.report({
|
|
40
|
+
node: secondArg,
|
|
41
|
+
messageId: 'dynamicHttpsErrors',
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
NewExpression(node) {
|
|
49
|
+
return checkForHttpsError(node);
|
|
50
|
+
},
|
|
51
|
+
CallExpression(node) {
|
|
52
|
+
return checkForHttpsError(node);
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=dynamic-https-errors.js.map
|