@chedched/eslint-plugin

0.0.4 • Public • Published

Description

These rules are custom eslint rules.

Installation

A) Add "@chedched/eslint-plugin": "^x.x.x" to the dependencies inside the package.json of the angular app. Use a suitable version number.

B) Execute npm install.

C) In the .eslintrc.json of the angular app, add

{
    "files": ["*.ts"],
    "plugins": ["@chedched"],
    "rules": {
        "@chedched/no-operator-in-switch-cases": "error",
        "@chedched/readonly-injectables": "error",
        "@chedched/take-until-before-subscription": "error"
    }
},

to the overrides property.

Rules

no-operator-in-switch-cases

Enforces the application to not have operators like "OR" or "AND" in cases of a switch statement. Operators in switch statements are prohibited, for multi-criteria-cases fall-throughs should be used instead.

Examples of incorrect code for this rule:

switch (expr) {
  case 'Oranges' || 'Apples':
                 ~~ Operational operator in switch case
    break;
  default:
    return foo;
}

switch (expr) {
  case 'Oranges' && 'Apples':
                 ~~ Operational operator in switch case
    break;
  default:
    return foo;
}

Examples of correct code for this rule:

switch (expr) {
  case 'Oranges':
    break;
  case 'Apples':
    break;
  default:
    return foo;
}

switch (expr) {
  case 'Oranges':
  case 'Apples':
    break;
  default:
    return foo;
}

readonly-injectables

An injected dependency is usually created as a singleton and overwriting it breaks the whole concept of dependency injection pattern. This rule enforces the application to prepend an injected dependence with a readonly statement.

This rule is inspired by https://github.com/shpaq23/custom-eslint-rules.

Examples of incorrect code for this rule:

constructor(private restService: RestService)
                  ~~ not preceded by readonly

Examples of correct code for this rule:

constructor(private readonly restService: RestService)

take-until-before-subscription

Enforces the application to properly unsubscribe from subscriptions. This rule makes sure that:

  • All subscriptions are preceded by a pipe statement
  • The last argument of the pipe preceding a subscription is a takeUntil statement
  • The takeUntil statement has a single argument
  • The single argument of the takeUntil statement is a property of the class
  • The single argument of the takeUntil statement is initialized as a subject
  • The component containing the subscription implements an ngOnDestroy method
  • The subject used as argument for the takeUntil statement is called with next and complete in the ngOnDestroy method of the component

Examples of incorrect code for this rule:

this.rest.method(this.id).subscribe();
                        ~~ no preceded by pipe

this.rest.method(this.id).pipe(undefined).subscribe();
                               ~~~~~~~~~~ no takeUntil argument

this.rest.method(this.id).pipe(takeUntil(this.ngUnsubscribe), undefined).subscribe();
                                                              ~~~~~~~~~~ takeUntil is not last argument of pipe

this.rest.method(this.id).pipe(takeUntil(this.ngUnsubscribe, undefined)).subscribe();
                                                             ~~~~~~~~~ takeUntil does not take a single argument

@Component({
    selector: 'app-component',
    styleUrls: ['./app-component.component.scss'],
    templateUrl: './app-component.component.html',
})
export class AppComponentComponent implements OnDestroy, OnInit {
    ngUnsubscribe = new NotASubject();
                    ~~~~~~~~~~~~~~~~~~ takeUntil argument not initialized as subject

    foo() {
      this.rest.method(this.id).pipe(takeUntil(this.ngUnsubscribe)).subscribe();
    }

    ngOnDestroy() {
      this.ngUnsubscribe.next();
      this.ngUnsubscribe.complete();
    }
}

@Component({
    selector: 'app-component',
    styleUrls: ['./app-component.component.scss'],
    templateUrl: './app-component.component.html',
})
export class AppComponentComponent implements OnDestroy, OnInit {
    ngUnsubscribe = new Subject();

    foo() {
      this.rest.method(this.id).pipe(takeUntil(this.ngUnsubscribe)).subscribe();
    }

    ~~~~~~~~~~~~~~~~~~ no ngOnDestroy method
}

@Component({
    selector: 'app-component',
    styleUrls: ['./app-component.component.scss'],
    templateUrl: './app-component.component.html',
})
export class AppComponentComponent implements OnDestroy, OnInit {
    ngUnsubscribe = new Subject();

    foo() {
      this.rest.method(this.id).pipe(takeUntil(this.ngUnsubscribe)).subscribe();
    }

    ngOnDestroy() {
      this.ngUnsubscribe.NeitherNextNorComplete();
                        ~~~~~~~~~~~~~~~~~~~~~~~~~ takeUntil argument not called with .next() and .complete()
    }
}

Examples of correct code for this rule:

@Component({
    selector: 'app-component',
    styleUrls: ['./app-component.component.scss'],
    templateUrl: './app-component.component.html',
})
export class AppComponentComponent implements OnDestroy, OnInit {
    ngUnsubscribe = new Subject();

    foo() {
      this.rest.method(this.id).pipe(takeUntil(this.ngUnsubscribe)).subscribe();
    }

    ngOnDestroy() {
      this.ngUnsubscribe.next();
      this.ngUnsubscribe.complete();
    }
}

Publish

  • Install all dependencies with npm install
  • Increase version number in package.json
  • Build plugin with npm run-script build
  • Upload to NPM with npm publish --access public

Readme

Keywords

none

Package Sidebar

Install

npm i @chedched/eslint-plugin

Weekly Downloads

1

Version

0.0.4

License

MIT

Unpacked Size

55 kB

Total Files

21

Last publish

Collaborators

  • chedched