Skip to content

Commit 2c56dbf

Browse files
garritfraclaude
andauthored
feat(core): Add options-sorted-alphabetically lint rule for community nodes (#27886)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 34931a7 commit 2c56dbf

6 files changed

Lines changed: 665 additions & 0 deletions

File tree

packages/@n8n/eslint-plugin-community-nodes/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export default [
5959
| [node-class-description-icon-missing](docs/rules/node-class-description-icon-missing.md) | Node class description must have an `icon` property defined | ✅ ☑️ | | | 💡 |
6060
| [node-connection-type-literal](docs/rules/node-connection-type-literal.md) | Disallow string literals in node description `inputs`/`outputs` — use `NodeConnectionTypes` enum instead | ✅ ☑️ | | 🔧 | |
6161
| [node-usable-as-tool](docs/rules/node-usable-as-tool.md) | Ensure node classes have usableAsTool property | ✅ ☑️ | | 🔧 | |
62+
| [options-sorted-alphabetically](docs/rules/options-sorted-alphabetically.md) | Enforce alphabetical ordering of options arrays in n8n node properties | | ✅ ☑️ | | |
6263
| [package-name-convention](docs/rules/package-name-convention.md) | Enforce correct package naming convention for n8n community nodes | ✅ ☑️ | | | 💡 |
6364
| [resource-operation-pattern](docs/rules/resource-operation-pattern.md) | Enforce proper resource/operation pattern for better UX in n8n nodes | | ✅ ☑️ | | |
6465

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Enforce alphabetical ordering of options arrays in n8n node properties (`@n8n/community-nodes/options-sorted-alphabetically`)
2+
3+
⚠️ This rule _warns_ in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
## Rule Details
8+
9+
Warns when an `options`-type parameter has its options array not sorted alphabetically by name. Applies to all `type: 'options'` parameters — including `resource`, `operation`, and any other dropdowns.
10+
11+
Alphabetical ordering is an [official n8n UI design requirement](https://docs.n8n.io/integrations/creating-nodes/plan/node-ui-design/#lists) and the most frequently flagged issue in community node reviews.
12+
13+
Comparison is case-insensitive and locale-aware (handles non-ASCII names such as Spanish or Portuguese labels).
14+
15+
## Examples
16+
17+
### ❌ Incorrect
18+
19+
```typescript
20+
export class MyNode implements INodeType {
21+
description: INodeTypeDescription = {
22+
displayName: 'My Service',
23+
name: 'myService',
24+
properties: [
25+
{
26+
displayName: 'Resource',
27+
name: 'resource',
28+
type: 'options',
29+
options: [
30+
{ name: 'User', value: 'user' },
31+
{ name: 'Contact', value: 'contact' }, // out of order
32+
{ name: 'Project', value: 'project' },
33+
],
34+
default: 'user',
35+
},
36+
],
37+
};
38+
}
39+
```
40+
41+
### ✅ Correct
42+
43+
```typescript
44+
export class MyNode implements INodeType {
45+
description: INodeTypeDescription = {
46+
displayName: 'My Service',
47+
name: 'myService',
48+
properties: [
49+
{
50+
displayName: 'Resource',
51+
name: 'resource',
52+
type: 'options',
53+
options: [
54+
{ name: 'Contact', value: 'contact' },
55+
{ name: 'Project', value: 'project' },
56+
{ name: 'User', value: 'user' },
57+
],
58+
default: 'contact',
59+
},
60+
],
61+
};
62+
}
63+
```

packages/@n8n/eslint-plugin-community-nodes/src/plugin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const configs = {
3131
'@n8n/community-nodes/no-credential-reuse': 'error',
3232
'@n8n/community-nodes/no-http-request-with-manual-auth': 'error',
3333
'@n8n/community-nodes/icon-validation': 'error',
34+
'@n8n/community-nodes/options-sorted-alphabetically': 'warn',
3435
'@n8n/community-nodes/resource-operation-pattern': 'warn',
3536
'@n8n/community-nodes/credential-documentation-url': 'error',
3637
'@n8n/community-nodes/node-class-description-icon-missing': 'error',
@@ -53,6 +54,7 @@ const configs = {
5354
'@n8n/community-nodes/no-credential-reuse': 'error',
5455
'@n8n/community-nodes/no-http-request-with-manual-auth': 'error',
5556
'@n8n/community-nodes/icon-validation': 'error',
57+
'@n8n/community-nodes/options-sorted-alphabetically': 'warn',
5658
'@n8n/community-nodes/credential-documentation-url': 'error',
5759
'@n8n/community-nodes/resource-operation-pattern': 'warn',
5860
'@n8n/community-nodes/node-class-description-icon-missing': 'error',

packages/@n8n/eslint-plugin-community-nodes/src/rules/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { NoRestrictedImportsRule } from './no-restricted-imports.js';
1414
import { NodeClassDescriptionIconMissingRule } from './node-class-description-icon-missing.js';
1515
import { NodeConnectionTypeLiteralRule } from './node-connection-type-literal.js';
1616
import { NodeUsableAsToolRule } from './node-usable-as-tool.js';
17+
import { OptionsSortedAlphabeticallyRule } from './options-sorted-alphabetically.js';
1718
import { PackageNameConventionRule } from './package-name-convention.js';
1819
import { ResourceOperationPatternRule } from './resource-operation-pattern.js';
1920

@@ -24,6 +25,7 @@ export const rules = {
2425
'credential-password-field': CredentialPasswordFieldRule,
2526
'no-deprecated-workflow-functions': NoDeprecatedWorkflowFunctionsRule,
2627
'node-usable-as-tool': NodeUsableAsToolRule,
28+
'options-sorted-alphabetically': OptionsSortedAlphabeticallyRule,
2729
'package-name-convention': PackageNameConventionRule,
2830
'credential-test-required': CredentialTestRequiredRule,
2931
'no-credential-reuse': NoCredentialReuseRule,

0 commit comments

Comments
 (0)