diff --git a/README.md b/README.md
index 05f3bab..c5ea161 100644
--- a/README.md
+++ b/README.md
@@ -80,6 +80,7 @@ If you would like to propose a challenge, this project is open source, so feel f
+
## Contributors ✨
@@ -89,7 +90,7 @@ If you would like to propose a challenge, this project is open source, so feel f
diff --git a/nx.json b/nx.json
index 3a2294b..49bc144 100644
--- a/nx.json
+++ b/nx.json
@@ -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"]
diff --git a/tools/eslint-rules/index.ts b/tools/eslint-rules/index.ts
new file mode 100644
index 0000000..3389607
--- /dev/null
+++ b/tools/eslint-rules/index.ts
@@ -0,0 +1,8 @@
+import {
+ rule as forbiddenEnum,
+ RULE_NAME as forbiddenEnumName,
+} from './rules/forbidden-enum';
+
+module.exports = {
+ rules: { [forbiddenEnumName]: forbiddenEnum },
+};
diff --git a/tools/eslint-rules/jest.config.ts b/tools/eslint-rules/jest.config.ts
new file mode 100644
index 0000000..dccf67a
--- /dev/null
+++ b/tools/eslint-rules/jest.config.ts
@@ -0,0 +1,13 @@
+/* eslint-disable */
+export default {
+ displayName: 'eslint-rules',
+ preset: '../../jest.preset.js',
+ transform: {
+ '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }],
+ },
+ moduleFileExtensions: ['ts', 'js', 'html'],
+ coverageDirectory: '../../coverage/tools/eslint-rules',
+ moduleNameMapper: {
+ '@eslint/eslintrc': '@eslint/eslintrc/dist/eslintrc-universal.cjs',
+ },
+};
diff --git a/tools/eslint-rules/project.json b/tools/eslint-rules/project.json
new file mode 100644
index 0000000..39f4eb6
--- /dev/null
+++ b/tools/eslint-rules/project.json
@@ -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
+ }
+ }
+ }
+ }
+}
diff --git a/tools/eslint-rules/rules/forbidden-enum.README.md b/tools/eslint-rules/rules/forbidden-enum.README.md
new file mode 100644
index 0000000..766e292
--- /dev/null
+++ b/tools/eslint-rules/rules/forbidden-enum.README.md
@@ -0,0 +1,34 @@
+Create a eslint rule to forbid enums
+
+> 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.
+
+
+
+
+
+
+_You can ask any question on_
diff --git a/tools/eslint-rules/rules/forbidden-enum.spec.ts b/tools/eslint-rules/rules/forbidden-enum.spec.ts
new file mode 100644
index 0000000..82c051e
--- /dev/null
+++ b/tools/eslint-rules/rules/forbidden-enum.spec.ts
@@ -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: [],
+});
diff --git a/tools/eslint-rules/rules/forbidden-enum.ts b/tools/eslint-rules/rules/forbidden-enum.ts
new file mode 100644
index 0000000..527a47b
--- /dev/null
+++ b/tools/eslint-rules/rules/forbidden-enum.ts
@@ -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 {};
+ },
+});
diff --git a/tools/eslint-rules/tsconfig.json b/tools/eslint-rules/tsconfig.json
new file mode 100644
index 0000000..5116586
--- /dev/null
+++ b/tools/eslint-rules/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "module": "commonjs"
+ },
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.lint.json"
+ },
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ]
+}
diff --git a/tools/eslint-rules/tsconfig.lint.json b/tools/eslint-rules/tsconfig.lint.json
new file mode 100644
index 0000000..bb717c5
--- /dev/null
+++ b/tools/eslint-rules/tsconfig.lint.json
@@ -0,0 +1,9 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "types": ["node"]
+ },
+ "exclude": ["**/*.spec.ts"],
+ "include": ["**/*.ts"]
+}
diff --git a/tools/eslint-rules/tsconfig.spec.json b/tools/eslint-rules/tsconfig.spec.json
new file mode 100644
index 0000000..546f128
--- /dev/null
+++ b/tools/eslint-rules/tsconfig.spec.json
@@ -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"]
+}