Skip to content
This repository has been archived by the owner on May 23, 2021. It is now read-only.

Commit

Permalink
feat: add ngrx-no-multiple-stores (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
timdeschryver authored Dec 22, 2019
1 parent 4f1ad92 commit 985f24d
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ To enable all rules, use the `recommended` configuration file.
| ngrx-no-duplicate-action-types | An action type must be unique | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-no-duplicate-action-types/fixture.ts.lint) |
| ngrx-no-effect-decorator | The createEffect creator function is preferred | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-no-effect-decorator/fixture.ts.lint) |
| ngrx-no-multiple-actions-in-effects | An Effect should not return multiple actions | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-no-multiple-actions-in-effects/fixture.ts.lint) |
| ngrx-no-multiple-stores | Store should at most be one time injected | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-no-multiple-stores/fixture.ts.lint) |
| ngrx-no-typed-store | A store should not be typed | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-no-typed-store/fixture.ts.lint) |
| ngrx-selector-for-select | Using string or props drilling is not preferred, use a selector instead | [Example](https://github.com/timdeschryver/ngrx-tslint-rules/tree/master/test/rules/ngrx-selector-for-select/fixture.ts.lint) |

Expand Down
3 changes: 3 additions & 0 deletions src/recommended.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ module.exports = {
'ngrx-no-multiple-actions-in-effects': {
severity: 'warning',
},
'ngrx-no-multiple-stores': {
severity: 'warning',
},
'ngrx-no-typed-store': {
severity: 'warning',
},
Expand Down
46 changes: 46 additions & 0 deletions src/rules/ngrxNoMultipleStoresRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { tsquery } from '@phenomnomnominal/tsquery'
import * as Lint from 'tslint'
import * as ts from 'typescript'

export class Rule extends Lint.Rules.TypedRule {
public static metadata: Lint.IRuleMetadata = {
description: 'The should only be one story injected',
descriptionDetails: 'There is only one global store',
options: null,
optionsDescription: 'Not configurable',
requiresTypeInfo: true,
ruleName: 'ngrx-no-multiple-stores',
type: 'maintainability',
typescriptOnly: true,
}

public static FAILURE_STRING = 'Store should at most be one time injected'
private CONSTRUCTOR_QUERY = `ClassDeclaration > Constructor`
private PARAMETER_QUERY = `Parameter > TypeReference > Identifier[name="Store"]`

public applyWithProgram(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
const constructors = tsquery(sourceFile, this.CONSTRUCTOR_QUERY)
const failures = constructors
.map(ctor => tsquery(ctor, this.PARAMETER_QUERY))
.reduce(
(hits, parameters) => {
if (parameters.length <= 1) {
return hits
}
const { parent: typeRefNode } = parameters.pop()
const { parent: parameterNode } = typeRefNode
const failure = new Lint.RuleFailure(
sourceFile,
parameterNode.getStart(),
parameterNode.getStart() + parameterNode.getWidth(),
Rule.FAILURE_STRING,
this.ruleName,
)
return [...hits, failure]
},
[] as Lint.RuleFailure[],
)

return failures
}
}
2 changes: 1 addition & 1 deletion src/rules/ngrxNoTypedStoreRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class Rule extends Lint.Rules.TypedRule {
): Lint.RuleFailure[] {
const parameters = tsquery(
sourceFile,
`ClassDeclaration > Constructor TypeReference > Identifier[name="Store"]`,
`ClassDeclaration > Constructor Parameter > TypeReference > Identifier[name="Store"]`,
) as ts.Identifier[]

const hits = parameters
Expand Down
23 changes: 23 additions & 0 deletions test/rules/ngrx-no-multiple-stores/fixture.ts.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Store } from '@ngrx/store'

export class NotOk {
constructor(store: Store<{}>, store2: Store<{}>){}
~~~~~~~~~~~~~~~~~ [error]
}

export class NoCtorOK {
}

export class EmptyOk {
constructor(){}
}

export class OneOk {
constructor(private store: Store<{}>){}
}

export class OnePlusExtraOk {
constructor(private store: Store<{}>, data: object){}
}

[error]: Store should at most be one time injected
12 changes: 12 additions & 0 deletions test/rules/ngrx-no-multiple-stores/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"baseUrl": ".",
"lib": ["es2015"],
"noEmit": true,
"paths": {
"@ngrx/store": ["../../../node_modules/@ngrx/store"]
},
"skipLibCheck": true,
"target": "es5"
}
}
7 changes: 7 additions & 0 deletions test/rules/ngrx-no-multiple-stores/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"defaultSeverity": "error",
"rules": {
"ngrx-no-multiple-stores": true
},
"rulesDirectory": ["../../../dist/rules"]
}

0 comments on commit 985f24d

Please sign in to comment.