feat(challenge26): forbidden enum rule

This commit is contained in:
thomas
2023-07-03 22:36:08 +02:00
parent 4eb92eae9f
commit 3be7f31bea
11 changed files with 165 additions and 2 deletions

View File

@@ -80,6 +80,7 @@ If you would like to propose a challenge, this project is open source, so feel f
<a href="./libs/custom-plugin/src/generators/custom-library/README.md"><img src="https://img.shields.io/badge/25-Extends Nx Library generator-red" alt="extends lib generator"/></a>
<a href="./libs/custom-plugin/src/generators/feature-component/README.md"><img src="https://img.shields.io/badge/25-Component generator-orange" alt="Custom component generator"/></a>
<a href="./tools/eslint-rules/rules/forbidden-enum.README.md"><img src="https://img.shields.io/badge/26-Forbid enum Rule-green" alt="Forbid enum rules"/></a>
## Contributors ✨
@@ -89,7 +90,7 @@ If you would like to propose a challenge, this project is open source, so feel f
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://medium.com/@thomas.laforge"><img src="https://avatars.githubusercontent.com/u/30832608?s…00&u=6f0ad9676792f29fd7fe6e113df06213d384a813&v=4" width="100px;" alt="Thomas Laforge"/><br /><sub><b>Thomas Laforge</b></sub></a><br />25 🧩</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://medium.com/@thomas.laforge"><img src="https://avatars.githubusercontent.com/u/30832608?s…00&u=6f0ad9676792f29fd7fe6e113df06213d384a813&v=4" width="100px;" alt="Thomas Laforge"/><br /><sub><b>Thomas Laforge</b></sub></a><br />26 🧩</a></td>
</tr>
</tbody>
</table>

View File

@@ -27,7 +27,11 @@
"inputs": ["default", "^production"]
},
"lint": {
"inputs": ["default", "{workspaceRoot}/.eslintrc.json"]
"inputs": [
"default",
"{workspaceRoot}/.eslintrc.json",
"{workspaceRoot}/tools/eslint-rules/**/*"
]
},
"component-test": {
"inputs": ["default", "^production"]

View File

@@ -0,0 +1,8 @@
import {
rule as forbiddenEnum,
RULE_NAME as forbiddenEnumName,
} from './rules/forbidden-enum';
module.exports = {
rules: { [forbiddenEnumName]: forbiddenEnum },
};

View File

@@ -0,0 +1,13 @@
/* eslint-disable */
export default {
displayName: 'eslint-rules',
preset: '../../jest.preset.js',
transform: {
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/tools/eslint-rules',
moduleNameMapper: {
'@eslint/eslintrc': '@eslint/eslintrc/dist/eslintrc-universal.cjs',
},
};

View File

@@ -0,0 +1,21 @@
{
"name": "eslint-rules",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "tools/eslint-rules",
"targets": {
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "tools/eslint-rules/jest.config.ts",
"passWithNoTests": true
},
"configurations": {
"ci": {
"ci": true,
"codeCoverage": true
}
}
}
}
}

View File

@@ -0,0 +1,34 @@
<h1>Create a eslint rule to forbid enums</h1>
> Author: Thomas Laforge
### Information
Eslint is an amazing tool that helps developers avoid simple mistakes and adhere to company style guides.
In this first example, we will create a rule that forbids the use of enums. The rule will suggest using string unions instead of enums whenever you add an enum to your code. It is a straightforward rule for learning how to create rules.
You will also need to write tests to verify the rule's functionality.
To test the rule inside your project, add `"@nrwl/nx/workspace/forbidden-enum": "error"` to the `eslintrc.json` file and attempt to insert an enum into any project to witness the magic. 😇
To assist you with AST (Abstract Syntax Tree) definitions, you can visit the [AST explorer](https://astexplorer.net/) and use JavaScript, @typescript-eslint/parser, and Eslint-v8 as the transformation method. However, please note that you will only get the type information there. The transformation function may not work for TypeScript types since the editor is in JavaScript.
You can also check this [repo](https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin/src/rules) for eslint rule examples.
### Submitting your work
1. Fork the project
2. clone it
3. npm ci
4. _...work on it_
5. `npx nx test eslint-rules`
6. Commit your work
7. Submit a PR with a title beginning with **Answer:27** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A27+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="forbidden-enum"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A27+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="forbidden-enum solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="forbidden-enum blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -0,0 +1,11 @@
import { TSESLint } from '@typescript-eslint/utils';
import { rule, RULE_NAME } from './forbidden-enum';
const ruleTester = new TSESLint.RuleTester({
parser: require.resolve('@typescript-eslint/parser'),
});
ruleTester.run(RULE_NAME, rule, {
valid: [`const example = true;`],
invalid: [],
});

View File

@@ -0,0 +1,37 @@
/**
* This file sets you up with structure needed for an ESLint rule.
*
* It leverages utilities from @typescript-eslint to allow TypeScript to
* provide autocompletions etc for the configuration.
*
* Your rule's custom logic will live within the create() method below
* and you can learn more about writing ESLint rules on the official guide:
*
* https://eslint.org/docs/developer-guide/working-with-rules
*
* You can also view many examples of existing rules here:
*
* https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin/src/rules
*/
import { ESLintUtils } from '@typescript-eslint/utils';
// NOTE: The rule will be available in ESLint configs as "@nx/workspace/forbidden-enum"
export const RULE_NAME = 'forbidden-enum';
export const rule = ESLintUtils.RuleCreator(() => __filename)({
name: RULE_NAME,
meta: {
type: 'problem',
docs: {
description: ``,
recommended: 'error',
},
schema: [],
messages: {},
},
defaultOptions: [],
create(context) {
return {};
},
});

View File

@@ -0,0 +1,16 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs"
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lint.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"]
},
"exclude": ["**/*.spec.ts"],
"include": ["**/*.ts"]
}

View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"]
}