Skip to content

Instantly share code, notes, and snippets.

@LouisSung
Last active October 8, 2021 08:53
Show Gist options
  • Save LouisSung/6b64f7597fba12a7bdc719f1a225eb55 to your computer and use it in GitHub Desktop.
Save LouisSung/6b64f7597fba12a7bdc719f1a225eb55 to your computer and use it in GitHub Desktop.
Strict ESLint and commitlint rules (configs) for NestJS (move to: https://github.com/LouisSung/TypeScript-Linter_and_Git_Hooks)
/**
* @file [commitlint Config] Strict commitlint rules for Sysmaker API
* @version v1.0.0
* @author LouisSung
* @license MIT
* @see https://commitlint.js.org/#/reference-rules
* @see https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/rules/src
* @see https://github.com/conventional-changelog/commitlint/blob/master/%40commitlint/config-conventional/index.js
* @see https://medium.com/@peter3036200/git-cz-%E8%A6%8F%E7%AF%84%E4%BD%A0%E7%9A%84-commit-%E8%A8%8A%E6%81%AF-9bd8f91b3267
*/
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'body-empty': [2, 'never'], // @LS: use `N/A` as body if you really have nothing to say... (NOT recommended)
'body-max-line-length': [2, 'always', 72], // both header and body length are limited to 72 chars
'header-max-length': [2, 'always', 72],
'subject-min-length': [2, 'always', 5], // start with imperative VERB and give INFORMATIVE info
'type-enum': [2, 'always',[
'feat', // e.g., `feat (copycat): support saying hi to copycat`
'fix', // e.g., `fix (coycat): make copycat great again`
'refactor', // e.g., `refactor: (copycat): make copycat faster`
'chore', // e.g., `chore (eslint): turn off annoying rules`
'WIP', // e.g., `WIP: back soon`
'revert', // e.g., `revert (a1bc): rollback for bug fix` (where a1bc is the target commit hash)
'docs', // e.g., `docs (copycat): update cat description`
'test', // e.g., `test (copydog): prove that cat is cuter than dog`
'merge', // e.g., `merge (develop): from branch 'feature/implement_api_copycat'` (where develop is the target branch)
]]
}
};
/**
* @file [ESLint Config] Strict ESLint rules for JavaScript and TypeScript (optimize for NestJS)
* @version v1.1.0
* @author LouisSung
* @license MIT
* @see https://eslint.org/docs/rules/
* @see https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#supported-rules
*/
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module'
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'prettier',
'prettier/@typescript-eslint'
],
root: true,
env: {
node: true,
jest: true,
},
rules: {
// ^^^ former lines are generated by NestJS CLI (except 'eslint:recommended')
// js
'arrow-body-style': ['warn', 'always'],
'arrow-parens': ['error', 'always'],
'arrow-spacing': ["error", {'before': true, 'after': true}],
'block-spacing': ['error', 'always'],
'brace-style': 'off', // ts
'comma-dangle': ['error', 'never'],
'comma-spacing': 'off', // ts
'comma-style': ['error', 'last'],
'complexity': ['warn', 10],
'computed-property-spacing': ['error', 'never', {'enforceForClassMembers': true}],
'curly': ['error', 'all'],
'default-param-last': 'off', // ts
'dot-notation': 'error',
'eol-last': ['error', 'always'],
'eqeqeq': ['error', 'always'],
'func-call-spacing': 'off', // ts
'func-names': ['error', 'always'],
'func-style': ['error', 'declaration', {'allowArrowFunctions': true }],
'generator-star-spacing': ['error', {'before': true, 'after': false}],
'guard-for-in': 'error',
'indent': 'off', // ts
'key-spacing': ['error', {'beforeColon': false, 'afterColon': true, 'mode': 'strict'}],
'keyword-spacing': ['error', {'before': true, 'after': true}],
'linebreak-style': ['error', 'unix'],
'max-classes-per-file': ['error', 4],
'max-depth': ['warn', 4],
'max-len': ['error', {'code': 140, 'tabWidth': 2}],
'max-lines': ['error', { max: 300, 'skipBlankLines': true, 'skipComments': true}],
'max-lines-per-function':['warn', {'max': 40, 'skipBlankLines': true, 'skipComments': true}],
'max-nested-callbacks': ['warn', 5],
'max-params': ['warn', 8],
'max-statements': ['warn', 40, {'ignoreTopLevelFunctions': true}],
'max-statements-per-line': ['error', {'max': 3}],
'multiline-comment-style': ['warn', 'separate-lines'],
'multiline-ternary': ['error', 'always-multiline'],
'new-cap': ['error', {'newIsCap': true, 'capIsNew': false, 'properties': true}],
'newline-per-chained-call': ['warn', {'ignoreChainWithDepth': 4}],
'new-parens': ['error', 'always'],
'no-array-constructor': 'off', // ts
'no-bitwise': ['warn', {'allow': ['~'], 'int32Hint': true}],
'no-cond-assign': ['error', 'always'],
'no-confusing-arrow': 'error',
'no-constructor-return': 'error',
'no-continue': 'warn',
'no-delete-var': 'error',
'no-div-regex': 'warn',
'no-dupe-class-members': 'off', // ts
'no-duplicate-imports': ['error', {'includeExports': true}],
'no-else-return': 'warn',
'no-empty-function': 'off', // ts
'no-eq-null': 'error',
'no-eval': 'error',
'no-extend-native': 'error',
'no-extra-bind': 'error',
'no-extra-parens': 'off', // ts
'no-extra-semi': 'off', // ts
'no-floating-decimal': 'error',
'no-implicit-coercion': 'error',
'no-implicit-globals': 'error',
'no-implied-eval': 'error',
'no-invalid-this': 'error',
'no-iterator': 'error',
'no-irregular-whitespace': 'error',
'no-lone-blocks': 'error',
'no-lonely-if': 'warn',
'no-label-var': 'error',
'no-labels': 'error',
'no-loop-func': 'error',
'no-magic-numbers': 'off', // ts
'no-mixed-operators': ['error', {'allowSamePrecedence': true}],
'no-mixed-spaces-and-tabs': 'error',
'no-multi-assign': 'error',
'no-multi-spaces': ['error', {'ignoreEOLComments': true}],
'no-multi-str': 'error',
'no-multiple-empty-lines': ['error', {'max': 2, 'maxEOF': 0, 'maxBOF': 0}],
'no-negated-condition': 'warn',
'no-new': 'error',
'no-new-func': 'error',
'no-new-object': 'error',
'no-new-wrappers': 'error',
'no-octal-escape': 'error',
'no-param-reassign': 'error',
'no-redeclare': ['error', {'builtinGlobals': true}],
'no-restricted-globals': 'error',
'no-return-assign': 'error',
'no-return-await': 'error',
'no-script-url': 'error',
'no-self-assign': 'error',
'no-self-compare': 'error',
'no-sequences': 'error',
'no-shadow': ['warn', {'builtinGlobals': true, 'hoist': 'all'}],
'no-shadow-restricted-names': 'error',
'no-sparse-arrays': 'error',
'no-template-curly-in-string': 'error',
'no-throw-literal': 'error',
'no-trailing-spaces': 'error',
'no-undef': ['error', {'typeof': false}],
'no-undefined': 'error',
'no-underscore-dangle': ['error', {'allowAfterThis': true, 'allowAfterSuper': true, 'enforceInMethodNames': true}],
'no-unexpected-multiline': 'error',
'no-unmodified-loop-condition': 'warn',
'no-unneeded-ternary': 'warn',
'no-unreachable': 'warn',
'no-unsafe-finally': 'error',
'no-unused-expressions': 'off', // ts
'no-unused-vars': 'off', // ts
'no-use-before-define': 'off', // ts
'no-useless-call': 'error',
'no-useless-catch': 'warn',
'no-useless-concat': 'error',
'no-useless-constructor': 'off', // ts
'no-useless-rename': 'error',
'no-useless-return': 'error',
'no-var': 'error',
'no-void': 'warn',
'no-warning-comments': ['warn', {'terms': ['TODO'], 'location': 'start'}],
'no-whitespace-before-property': 'error',
'object-curly-newline': ['error', {'multiline': true, 'consistent': true}],
'object-curly-spacing': ['error', 'never'],
'object-property-newline': ['warn', {'allowAllPropertiesOnSameLine': true}],
'object-shorthand': ['warn', 'always', {'avoidQuotes': true}],
'one-var': ['error', {'initialized': 'never', 'uninitialized': 'consecutive'}],
'operator-assignment': ['error', 'always'],
'operator-linebreak': ['error', 'before'],
'padding-line-between-statements': ['warn',
{'blankLine': 'always', 'prev': '*', 'next': 'return'},
{'blankLine': 'always', 'prev': ['const', 'let', 'var'], 'next': '*'},
{'blankLine': 'any', 'prev': ['const', 'let', 'var'], 'next': ['const', 'let', 'var']}],
'padded-blocks': ['error', 'never'],
'prefer-arrow-callback': ['warn', {'allowNamedFunctions': false, 'allowUnboundThis': true}],
'prefer-const': ['error', {'destructuring': 'any'}],
'prefer-numeric-literals': 'warn',
'prefer-object-spread': 'warn',
'prefer-promise-reject-errors': 'error',
'prefer-regex-literals': 'error',
'prefer-rest-params': 'error',
'prefer-spread': 'error',
'prefer-template': 'error',
'quote-props': ['error', 'as-needed', {'numbers': true}],
'quotes': 'off', // ts
'radix': ['error', 'as-needed'],
'require-await': 'off', // ts
'require-yield': 'error',
'rest-spread-spacing': 'error',
'semi': 'off',
'semi-spacing': ['error', {'before': false, 'after': true}],
'semi-style': ['error', 'last'],
'sort-imports': ['warn', {'ignoreDeclarationSort': true}],
'space-before-blocks': ['error', 'always'],
'space-before-function-paren': 'off', // ts
'space-in-parens': ['error', 'never'],
'space-infix-ops': ['error',{'int32Hint': false}] ,
'space-unary-ops': ['error', {'words': true, 'nonwords': false}],
'strict': 'error',
'switch-colon-spacing': ['error', {'before': false, 'after': true}],
'spaced-comment': ['error', 'always'],
'symbol-description': 'warn',
'template-curly-spacing': ['error', 'never'],
'template-tag-spacing': ['error', 'never'],
'vars-on-top': 'error',
'valid-typeof': 'error',
'wrap-iife': 'warn',
'wrap-regex': 'error',
'yield-star-spacing': ['error', {'before': false, 'after': true}],
'yoda': 'warn',
// ts only
'@typescript-eslint/array-type': ['error', {default: 'generic'}],
'@typescript-eslint/consistent-type-definitions': ['error', 'interface'],
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'error',
'@typescript-eslint/explicit-member-accessibility': ['error',
{accessibility: 'explicit', overrides: {constructors: 'no-public'}}],
'@typescript-eslint/explicit-module-boundary-types': 'error',
'@typescript-eslint/member-delimiter-style': ['error',
{multiline: {delimiter: 'semi', requireLast: true}, singleline: {delimiter: 'semi', requireLast: true}}],
'@typescript-eslint/member-ordering': 'error',
'@typescript-eslint/naming-convention': 'error',
'@typescript-eslint/no-base-to-string': 'error',
'@typescript-eslint/no-dynamic-delete': 'error',
'@typescript-eslint/no-empty-interface': ['error', {allowSingleExtends: true}],
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-extra-non-null-assertion': 'error',
'@typescript-eslint/no-extraneous-class': 'off', // @LS: required for *.module
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-for-in-array': 'error',
'@typescript-eslint/no-implied-eval': 'error',
'@typescript-eslint/no-inferrable-types': 'error',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
'@typescript-eslint/no-require-imports': 'error',
'@typescript-eslint/no-this-alias': ['error', {allowedNames: ['self']}],
'@typescript-eslint/no-throw-literal': 'error',
'@typescript-eslint/no-type-alias': ['warn', {allowAliases: 'always', allowCallbacks: 'always',
allowLiterals: 'in-unions-and-intersections', allowMappedTypes: 'in-unions-and-intersections'}],
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'warn',
'@typescript-eslint/no-unnecessary-condition': 'warn',
'@typescript-eslint/no-unnecessary-qualifier': 'warn',
'@typescript-eslint/no-unnecessary-type-arguments': 'warn',
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/no-unused-vars-experimental': 'off', // @LS: annoying
'@typescript-eslint/prefer-as-const': 'error',
'@typescript-eslint/prefer-for-of': 'error',
'@typescript-eslint/prefer-function-type': 'warn',
'@typescript-eslint/prefer-includes': 'error',
'@typescript-eslint/prefer-namespace-keyword': 'error',
'@typescript-eslint/prefer-nullish-coalescing': 'warn',
'@typescript-eslint/prefer-optional-chain': 'warn',
'@typescript-eslint/prefer-readonly': 'warn',
'@typescript-eslint/prefer-readonly-parameter-types': 'off', // @LS: required for dependency injection
'@typescript-eslint/prefer-regexp-exec': 'error',
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
'@typescript-eslint/promise-function-async': 'error',
'@typescript-eslint/require-array-sort-compare': 'error',
'@typescript-eslint/restrict-plus-operands': ['error', {checkCompoundAssignments: true}],
'@typescript-eslint/restrict-template-expressions': 'warn',
'@typescript-eslint/strict-boolean-expressions': 'error',
'@typescript-eslint/switch-exhaustiveness-check': 'error',
'@typescript-eslint/type-annotation-spacing': 'error',
'@typescript-eslint/typedef': 'error',
'@typescript-eslint/unbound-method': 'warn',
'@typescript-eslint/unified-signatures': 'warn',
// ts replace js
'@typescript-eslint/brace-style': ['error', '1tbs', {allowSingleLine: true}],
'@typescript-eslint/comma-spacing': 'error',
'@typescript-eslint/default-param-last': 'warn',
'@typescript-eslint/func-call-spacing': ['error', 'never'],
'@typescript-eslint/indent': ['error', 2],
'@typescript-eslint/no-array-constructor': 'error',
'@typescript-eslint/no-dupe-class-members': 'error',
'@typescript-eslint/no-empty-function': 'off', // @LS: useful for placeholder (e.g., promise handling)
'@typescript-eslint/no-extra-parens': 'off', // @LS: may be useful to clarify things
'@typescript-eslint/no-extra-semi': 'error',
'@typescript-eslint/no-magic-numbers': ['off', // @LS: annoying
{ignoreNumericLiteralTypes: true, ignoreReadonlyClassProperties: true, ignoreEnums: false}],
'@typescript-eslint/no-unused-expressions': 'error',
'@typescript-eslint/no-unused-vars': ['warn', {vars: 'local', args: 'none'}],
'@typescript-eslint/no-use-before-define': 'error',
'@typescript-eslint/no-useless-constructor': 'off', // @LS: required for dependency injection
'@typescript-eslint/quotes': ['error', 'single', {'avoidEscape': true, 'allowTemplateLiterals': true}],
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/return-await': 'error',
'@typescript-eslint/semi': 'error',
'@typescript-eslint/space-before-function-paren': ['error', 'never']
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment