Skip to content

Commit d56f2d9

Browse files
committed
Add new rule no-private-routing-service
1 parent af84382 commit d56f2d9

File tree

6 files changed

+171
-0
lines changed

6 files changed

+171
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ Each rule has emojis denoting what configuration it belongs to and/or a :wrench:
7777
| :white_check_mark: | [no-observers](./docs/rules/no-observers.md) | disallow usage of observers |
7878
| :white_check_mark::wrench: | [no-old-shims](./docs/rules/no-old-shims.md) | disallow usage of old shims for modules |
7979
| :white_check_mark: | [no-on-calls-in-components](./docs/rules/no-on-calls-in-components.md) | disallow usage of `on` to call lifecycle hooks in components |
80+
| | [no-private-routing-service](./docs/rules/no-private-routing-service.md) | disallow injecting the private routing service |
8081
| :white_check_mark: | [no-restricted-resolver-tests](./docs/rules/no-restricted-resolver-tests.md) | disallow the use of patterns that use the restricted resolver in tests |
8182
| | [no-unnecessary-index-route](./docs/rules/no-unnecessary-index-route.md) | disallow unnecessary `index` route definition |
8283
| :white_check_mark::wrench: | [no-unnecessary-route-path-option](./docs/rules/no-unnecessary-route-path-option.md) | disallow unnecessary usage of the route `path` option |
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# no-private-routing-service
2+
3+
Disallow the use of the private `-routing` service.
4+
5+
There has been a public `router` service since Ember 2.16 and using the private routing service should be unnecessary.
6+
7+
## Examples
8+
9+
Examples of **incorrect** code for this rule:
10+
11+
```javascript
12+
import Component from '@ember/component';
13+
import { inject as service } from '@ember/service';
14+
15+
export default Component.extend({
16+
routing: service('-routing')
17+
});
18+
```
19+
20+
```javascript
21+
import Component from '@ember/component';
22+
23+
export default class MyComponent extends Component {
24+
@service('-routing') routing;
25+
}
26+
```
27+
28+
Examples of **correct** code for this rule:
29+
30+
```javascript
31+
import Component from '@ember/component';
32+
import { inject as service } from '@ember/service';
33+
34+
export default Component.extend({
35+
router: service('router')
36+
});
37+
```
38+
39+
```javascript
40+
import Component from '@ember/component';
41+
42+
export default class MyComponent extends Component {
43+
@service
44+
router;
45+
}
46+
```
47+
48+
## References
49+
50+
[Router RFC](https://github.com/emberjs/rfcs/blob/master/text/0095-router-service.md)

lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ module.exports = {
4040
'no-old-shims': require('./rules/no-old-shims'),
4141
'no-on-calls-in-components': require('./rules/no-on-calls-in-components'),
4242
'no-pause-test': require('./rules/no-pause-test'),
43+
'no-private-routing-service': require('./rules/no-private-routing-service'),
4344
'no-proxies': require('./rules/no-proxies'),
4445
'no-restricted-resolver-tests': require('./rules/no-restricted-resolver-tests'),
4546
'no-side-effects': require('./rules/no-side-effects'),

lib/recommended-rules.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ module.exports = {
4343
"ember/no-old-shims": "error",
4444
"ember/no-on-calls-in-components": "error",
4545
"ember/no-pause-test": "off",
46+
"ember/no-private-routing-service": "off",
4647
"ember/no-proxies": "off",
4748
"ember/no-restricted-resolver-tests": "error",
4849
"ember/no-side-effects": "error",
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
'use strict';
2+
3+
const emberUtils = require('../utils/ember');
4+
const types = require('../utils/types');
5+
6+
//------------------------------------------------------------------------------
7+
// Rule Definition
8+
//------------------------------------------------------------------------------
9+
10+
const ERROR_MESSAGE =
11+
"Don't inject the private '-routing' service. Instead use the public 'router' service.";
12+
13+
module.exports = {
14+
meta: {
15+
type: 'suggestion',
16+
docs: {
17+
description: 'disallow injecting the private routing service',
18+
category: 'Best Practices',
19+
recommended: false,
20+
url:
21+
'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/no-private-routing-service.md',
22+
},
23+
fixable: null,
24+
schema: [],
25+
},
26+
27+
ERROR_MESSAGE,
28+
29+
create(context) {
30+
const ROUTING_SERVICE_NAME = '-routing';
31+
32+
return {
33+
Property(node) {
34+
if (
35+
emberUtils.isInjectedServiceProp(node) &&
36+
node.value.arguments[0].value === ROUTING_SERVICE_NAME
37+
) {
38+
context.report({ node, message: ERROR_MESSAGE });
39+
}
40+
},
41+
ClassProperty(node) {
42+
if (!node.decorators || !types.isClassPropertyWithDecorator(node, 'service')) {
43+
return;
44+
}
45+
46+
const hasRoutingServiceDecorator = node.decorators.some(decorator => {
47+
const expression = decorator.expression;
48+
return (
49+
expression &&
50+
expression.arguments &&
51+
expression.arguments[0].value === ROUTING_SERVICE_NAME
52+
);
53+
});
54+
55+
if (hasRoutingServiceDecorator) {
56+
context.report({ node, message: ERROR_MESSAGE });
57+
}
58+
},
59+
};
60+
},
61+
};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//------------------------------------------------------------------------------
2+
// Requirements
3+
//------------------------------------------------------------------------------
4+
5+
const rule = require('../../../lib/rules/no-private-routing-service');
6+
const RuleTester = require('eslint').RuleTester;
7+
8+
const { ERROR_MESSAGE } = rule;
9+
10+
//------------------------------------------------------------------------------
11+
// Tests
12+
//------------------------------------------------------------------------------
13+
14+
const ruleTester = new RuleTester({
15+
parser: require.resolve('babel-eslint'),
16+
parserOptions: {
17+
ecmaVersion: 2015,
18+
sourceType: 'module',
19+
},
20+
});
21+
22+
ruleTester.run('no-private-routing-service', rule, {
23+
valid: [
24+
"export default Component.extend({ someService: service('routing') });",
25+
"export default Component.extend({ someService: service('-router') });",
26+
"export default Component.extend({ '-routing': service('routing') });",
27+
"export default Component.extend({ '-routing': service('-router') });",
28+
"Component.extend({ routing: someOtherFunction('-routing') });",
29+
'export default class MyComponent extends Component { @service router; }',
30+
"export default class MyComponent extends Component { @service('router') routing; }",
31+
'export default class MyComponent extends Component { @service routing; }',
32+
"export default class MyComponent extends Component { @service('routing') routing; }",
33+
`
34+
export default class MyComponent extends Component {
35+
@computed('-routing', 'lastName')
36+
get fullName() {
37+
return \`${this.firstName} ${this.lastName}\`;
38+
}
39+
}
40+
`,
41+
],
42+
invalid: [
43+
// Classic
44+
{
45+
code: "export default Component.extend({ routing: service('-routing') });",
46+
output: null,
47+
errors: [{ message: ERROR_MESSAGE, type: 'Property' }],
48+
},
49+
50+
// Octane
51+
{
52+
code: "export default class MyComponent extends Component { @service('-routing') routing; }",
53+
output: null,
54+
errors: [{ message: ERROR_MESSAGE, type: 'ClassProperty' }],
55+
},
56+
],
57+
});

0 commit comments

Comments
 (0)