ESLint plugin for Ember.js apps providing 97 specialized linting rules based on commonly known good practices in the Ember ecosystem
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Rules for Ember routes covering naming conventions, lifecycle management, and best practices. These rules help maintain consistency in route definitions and prevent common routing anti-patterns.
Rules governing route naming conventions and URL structure.
/**
* Disallow capital letters in route names
* Enforces kebab-case route naming convention
*/
'ember/no-capital-letters-in-routes': ESLintRule;
/**
* Enforce snake_case for route segments
* Maintains URL consistency
*/
'ember/routes-segments-snake-case': ESLintRule;
/**
* Enforce consistent route path style
* Standardizes route path definitions
*/
'ember/route-path-style': ESLintRule;Usage Examples:
// ❌ Bad - capital letters in route name (triggers no-capital-letters-in-routes)
this.route('userProfile');
// ✅ Good - kebab-case route name
this.route('user-profile');
// ❌ Bad - inconsistent segment casing (triggers routes-segments-snake-case)
this.route('user-profile', { path: '/userProfile/:userId' });
// ✅ Good - snake_case segments
this.route('user-profile', { path: '/user_profile/:user_id' });Rules preventing improper access patterns in routes.
/**
* Disallow controller access in routes
* Prevents tight coupling between routes and controllers
*/
'ember/no-controller-access-in-routes': ESLintRule;
/**
* Disallow accessing private routing service
* Prevents usage of internal routing APIs
*/
'ember/no-private-routing-service': ESLintRule;Usage Examples:
// ❌ Bad - accessing controller in route (triggers no-controller-access-in-routes)
export default class UserRoute extends Route {
setupController(controller, model) {
super.setupController(...arguments);
this.controllerFor('application').set('currentUser', model);
}
}
// ✅ Good - using services instead
export default class UserRoute extends Route {
@service currentUser;
setupController(controller, model) {
super.setupController(...arguments);
this.currentUser.setUser(model);
}
}Rules for route lifecycle management and method usage.
/**
* Disallow deprecated router transition methods
* Encourages modern transition APIs
*/
'ember/no-deprecated-router-transition-methods': ESLintRule;
/**
* Disallow unnecessary route path options
* Removes redundant path specifications
*/
'ember/no-unnecessary-route-path-option': ESLintRule;
/**
* Disallow unnecessary index routes
* Removes redundant index route definitions
*/
'ember/no-unnecessary-index-route': ESLintRule;Usage Examples:
// ❌ Bad - deprecated transition method (triggers no-deprecated-router-transition-methods)
this.transitionToRoute('user.profile');
// ✅ Good - modern transition method
this.transitionTo('user.profile');
// ❌ Bad - unnecessary path option (triggers no-unnecessary-route-path-option)
this.route('profile', { path: '/profile' });
// ✅ Good - default path matches route name
this.route('profile');
// ❌ Bad - unnecessary index route (triggers no-unnecessary-index-route)
this.route('users', function() {
this.route('index', { path: '/' });
});
// ✅ Good - index route is implicit
this.route('users');Rules for organizing route properties and maintaining consistent structure.
/**
* Enforce order of properties in routes
* Maintains consistent route structure
*/
'ember/order-in-routes': ESLintRule;
/**
* Disallow shadow route definitions
* Prevents route definition conflicts
*/
'ember/no-shadow-route-definition': ESLintRule;Usage Examples:
// ❌ Bad - incorrect property order (triggers order-in-routes)
export default Route.extend({
actions: {
save() {
// action logic
}
},
model() {
return this.store.findAll('user');
},
queryParams: {
sortBy: { refreshModel: true }
}
});
// ✅ Good - correct property order
export default Route.extend({
queryParams: {
sortBy: { refreshModel: true }
},
model() {
return this.store.findAll('user');
},
actions: {
save() {
// action logic
}
}
});
// ❌ Bad - shadow route definition (triggers no-shadow-route-definition)
// In router.js
this.route('users');
this.route('users', { path: '/people' }); // Shadows previous definition
// ✅ Good - unique route definitions
this.route('users');
this.route('people', { path: '/people' });Rules for route-specific properties and default values.
/**
* Check if property is a default route property
* Identifies standard route properties
*/
function isRouteDefaultProp(property: ASTNode): boolean;
/**
* Route-specific property validation
* Standard route properties that should not be overridden unnecessarily
*/
interface RouteProperties {
actions: ActionsHash;
concatenatedProperties: string[];
controller: string;
controllerName: string;
isDestroyed: boolean;
isDestroying: boolean;
mergedProperties: string[];
queryParams: QueryParamsConfig;
routeName: string;
templateName: string;
}Usage Examples:
// Default route properties - generally should not be overridden
export default Route.extend({
// ✅ Good - standard route implementation
model() {
return this.store.findAll('user');
},
setupController(controller, model) {
super.setupController(...arguments);
controller.set('users', model);
}
});
// Route with query params
export default Route.extend({
queryParams: {
page: { refreshModel: true },
sortBy: { refreshModel: true }
},
model(params) {
return this.store.query('user', {
page: params.page,
sort: params.sortBy
});
}
});