feat: Add cred-class-name-field-conventions ESLint rule for community nodes (no-changelog) (#31472)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garrit Franke 2026-06-01 13:57:54 +02:00 committed by GitHub
parent 9dd966b658
commit 8b718d2aae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 355 additions and 45 deletions

View File

@ -44,41 +44,43 @@ export default [
💡 Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).\
❌ Deprecated.
| Name                                | Description | 💼 | ⚠️ | 🔧 | 💡 | ❌ |
| :--------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :--- | :--- | :- | :- | :- |
| [ai-node-package-json](docs/rules/ai-node-package-json.md) | Enforce consistency between n8n.aiNodeSdkVersion and ai-node-sdk peer dependency in community node packages | ✅ ☑️ | | | | |
| [cred-class-field-icon-missing](docs/rules/cred-class-field-icon-missing.md) | Credential class must have an `icon` property defined | ✅ ☑️ | | | 💡 | |
| [cred-class-name-suffix](docs/rules/cred-class-name-suffix.md) | Credential class names must be suffixed with `Api` | ✅ ☑️ | | 🔧 | | |
| [cred-class-oauth2-naming](docs/rules/cred-class-oauth2-naming.md) | OAuth2 credentials must include `OAuth2` in the class name, `name`, and `displayName` | ✅ ☑️ | | 🔧 | | |
| [credential-documentation-url](docs/rules/credential-documentation-url.md) | Enforce valid credential documentationUrl format (URL or lowercase alphanumeric slug) | ✅ ☑️ | | 🔧 | | |
| [credential-password-field](docs/rules/credential-password-field.md) | Ensure credential fields with sensitive names have typeOptions.password = true | ✅ ☑️ | | 🔧 | | |
| [credential-test-required](docs/rules/credential-test-required.md) | Ensure credentials have a credential test | ✅ ☑️ | | | 💡 | |
| [icon-validation](docs/rules/icon-validation.md) | Validate node and credential icon files exist, are SVG format, and light/dark icons are different | ✅ ☑️ | | | 💡 | |
| [missing-paired-item](docs/rules/missing-paired-item.md) | Require pairedItem on INodeExecutionData objects in execute() methods to preserve item linking. | ✅ ☑️ | | | | |
| [n8n-object-validation](docs/rules/n8n-object-validation.md) | Validate the structure of the "n8n" object in community node package.json (required keys, types, and dist/ paths) | ✅ ☑️ | | | | |
| [no-credential-reuse](docs/rules/no-credential-reuse.md) | Prevent credential re-use security issues by ensuring nodes only reference credentials from the same package | ✅ ☑️ | | | 💡 | |
| [no-deprecated-workflow-functions](docs/rules/no-deprecated-workflow-functions.md) | Disallow usage of deprecated functions and types from n8n-workflow package | ✅ ☑️ | | | 💡 | |
| [no-forbidden-lifecycle-scripts](docs/rules/no-forbidden-lifecycle-scripts.md) | Ban lifecycle scripts (prepare, preinstall, postinstall, etc.) in community node packages | ✅ ☑️ | | | | |
| [no-http-request-with-manual-auth](docs/rules/no-http-request-with-manual-auth.md) | Disallow this.helpers.httpRequest() in functions that call this.getCredentials(). Use this.helpers.httpRequestWithAuthentication() instead. | ✅ ☑️ | | | | |
| [no-overrides-field](docs/rules/no-overrides-field.md) | Ban the "overrides" field in community node package.json | ✅ ☑️ | | | | |
| [no-restricted-globals](docs/rules/no-restricted-globals.md) | Disallow usage of restricted global variables in community nodes. | ✅ | | | | |
| [no-restricted-imports](docs/rules/no-restricted-imports.md) | Disallow usage of restricted imports in community nodes. | ✅ | | | | |
| [no-runtime-dependencies](docs/rules/no-runtime-dependencies.md) | Disallow non-empty "dependencies" in community node package.json | ✅ ☑️ | | | | |
| [no-template-placeholders](docs/rules/no-template-placeholders.md) | Disallow unresolved template placeholders in package.json | ✅ ☑️ | | | | |
| [node-class-description-icon-missing](docs/rules/node-class-description-icon-missing.md) | Node class description must have an `icon` property defined. Deprecated: use `require-node-description-fields` instead. | | | | 💡 | ❌ |
| [node-connection-type-literal](docs/rules/node-connection-type-literal.md) | Disallow string literals in node description `inputs`/`outputs` — use `NodeConnectionTypes` enum instead | ✅ ☑️ | | 🔧 | | |
| [node-operation-error-itemindex](docs/rules/node-operation-error-itemindex.md) | Require { itemIndex } in NodeOperationError / NodeApiError options inside item loops | ✅ ☑️ | | | | |
| [node-usable-as-tool](docs/rules/node-usable-as-tool.md) | Ensure node classes have usableAsTool property | ✅ ☑️ | | 🔧 | | |
| [options-sorted-alphabetically](docs/rules/options-sorted-alphabetically.md) | Enforce alphabetical ordering of options arrays in n8n node properties | | ✅ ☑️ | | | |
| [package-name-convention](docs/rules/package-name-convention.md) | Enforce correct package naming convention for n8n community nodes | ✅ ☑️ | | | 💡 | |
| [require-community-node-keyword](docs/rules/require-community-node-keyword.md) | Require the "n8n-community-node-package" keyword in community node package.json | | ✅ ☑️ | 🔧 | | |
| [require-continue-on-fail](docs/rules/require-continue-on-fail.md) | Require continueOnFail() handling in execute() methods of node classes | ✅ ☑️ | | | | |
| [require-node-api-error](docs/rules/require-node-api-error.md) | Require NodeApiError or NodeOperationError for error wrapping in catch blocks. Raw errors lose HTTP context in the n8n UI. | ✅ ☑️ | | | | |
| [require-node-description-fields](docs/rules/require-node-description-fields.md) | Node class description must define all required fields: icon, subtitle | ✅ ☑️ | | | | |
| [resource-operation-pattern](docs/rules/resource-operation-pattern.md) | Enforce proper resource/operation pattern for better UX in n8n nodes | | ✅ ☑️ | | | |
| [valid-credential-references](docs/rules/valid-credential-references.md) | Ensure credentials referenced in node descriptions exist as credential classes in the package | ✅ ☑️ | | | 💡 | |
| [valid-description](docs/rules/valid-description.md) | Require a non-empty "description" field in community node package.json | ✅ ☑️ | | | | |
| [valid-peer-dependencies](docs/rules/valid-peer-dependencies.md) | Require community node package.json peerDependencies to contain only "n8n-workflow": "*" (and optionally "ai-node-sdk") | ✅ ☑️ | | 🔧 | | |
| [webhook-lifecycle-complete](docs/rules/webhook-lifecycle-complete.md) | Require webhook trigger nodes to implement the complete webhookMethods lifecycle (checkExists, create, delete) | ✅ ☑️ | | | | |
| Name                                | Description | 💼 | ⚠️ | 🔧 | 💡 | ❌ |
| :--------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--- | :--- | :- | :- | :- |
| [ai-node-package-json](docs/rules/ai-node-package-json.md) | Enforce consistency between n8n.aiNodeSdkVersion and ai-node-sdk peer dependency in community node packages | ✅ ☑️ | | | | |
| [cred-class-field-icon-missing](docs/rules/cred-class-field-icon-missing.md) | Credential class must have an `icon` property defined | ✅ ☑️ | | | 💡 | |
| [cred-class-name-field-conventions](docs/rules/cred-class-name-field-conventions.md) | Credential `name` field must end with `Api` and start with a lowercase letter | ✅ ☑️ | | 🔧 | | |
| [cred-class-name-suffix](docs/rules/cred-class-name-suffix.md) | Credential class names must be suffixed with `Api` | ✅ ☑️ | | 🔧 | | |
| [cred-class-oauth2-naming](docs/rules/cred-class-oauth2-naming.md) | OAuth2 credentials must include `OAuth2` in the class name, `name`, and `displayName` | ✅ ☑️ | | 🔧 | | |
| [credential-documentation-url](docs/rules/credential-documentation-url.md) | Enforce valid credential documentationUrl format (URL or lowercase alphanumeric slug) | ✅ ☑️ | | 🔧 | | |
| [credential-password-field](docs/rules/credential-password-field.md) | Ensure credential fields with sensitive names have typeOptions.password = true | ✅ ☑️ | | 🔧 | | |
| [credential-test-required](docs/rules/credential-test-required.md) | Ensure credentials have a credential test | ✅ ☑️ | | | 💡 | |
| [icon-validation](docs/rules/icon-validation.md) | Validate node and credential icon files exist, are SVG format, and light/dark icons are different | ✅ ☑️ | | | 💡 | |
| [missing-paired-item](docs/rules/missing-paired-item.md) | Require pairedItem on INodeExecutionData objects in execute() methods to preserve item linking. | ✅ ☑️ | | | | |
| [n8n-object-validation](docs/rules/n8n-object-validation.md) | Validate the structure of the "n8n" object in community node package.json (required keys, types, and dist/ paths) | ✅ ☑️ | | | | |
| [no-builder-hint-leakage](docs/rules/no-builder-hint-leakage.md) | Disallow wire-format expression syntax (={{...}}) and NodeConnectionType string literals in builderHint texts and AI-builder prompts. Use expr() and SDK-canonical references instead. | ✅ ☑️ | | | | |
| [no-credential-reuse](docs/rules/no-credential-reuse.md) | Prevent credential re-use security issues by ensuring nodes only reference credentials from the same package | ✅ ☑️ | | | 💡 | |
| [no-deprecated-workflow-functions](docs/rules/no-deprecated-workflow-functions.md) | Disallow usage of deprecated functions and types from n8n-workflow package | ✅ ☑️ | | | 💡 | |
| [no-forbidden-lifecycle-scripts](docs/rules/no-forbidden-lifecycle-scripts.md) | Ban lifecycle scripts (prepare, preinstall, postinstall, etc.) in community node packages | ✅ ☑️ | | | | |
| [no-http-request-with-manual-auth](docs/rules/no-http-request-with-manual-auth.md) | Disallow this.helpers.httpRequest() in functions that call this.getCredentials(). Use this.helpers.httpRequestWithAuthentication() instead. | ✅ ☑️ | | | | |
| [no-overrides-field](docs/rules/no-overrides-field.md) | Ban the "overrides" field in community node package.json | ✅ ☑️ | | | | |
| [no-restricted-globals](docs/rules/no-restricted-globals.md) | Disallow usage of restricted global variables in community nodes. | ✅ | | | | |
| [no-restricted-imports](docs/rules/no-restricted-imports.md) | Disallow usage of restricted imports in community nodes. | ✅ | | | | |
| [no-runtime-dependencies](docs/rules/no-runtime-dependencies.md) | Disallow non-empty "dependencies" in community node package.json | ✅ ☑️ | | | | |
| [no-template-placeholders](docs/rules/no-template-placeholders.md) | Disallow unresolved template placeholders in package.json | ✅ ☑️ | | | | |
| [node-class-description-icon-missing](docs/rules/node-class-description-icon-missing.md) | Node class description must have an `icon` property defined. Deprecated: use `require-node-description-fields` instead. | | | | 💡 | ❌ |
| [node-connection-type-literal](docs/rules/node-connection-type-literal.md) | Disallow string literals in node description `inputs`/`outputs` — use `NodeConnectionTypes` enum instead | ✅ ☑️ | | 🔧 | | |
| [node-operation-error-itemindex](docs/rules/node-operation-error-itemindex.md) | Require { itemIndex } in NodeOperationError / NodeApiError options inside item loops | ✅ ☑️ | | | | |
| [node-usable-as-tool](docs/rules/node-usable-as-tool.md) | Ensure node classes have usableAsTool property | ✅ ☑️ | | 🔧 | | |
| [options-sorted-alphabetically](docs/rules/options-sorted-alphabetically.md) | Enforce alphabetical ordering of options arrays in n8n node properties | | ✅ ☑️ | | | |
| [package-name-convention](docs/rules/package-name-convention.md) | Enforce correct package naming convention for n8n community nodes | ✅ ☑️ | | | 💡 | |
| [require-community-node-keyword](docs/rules/require-community-node-keyword.md) | Require the "n8n-community-node-package" keyword in community node package.json | | ✅ ☑️ | 🔧 | | |
| [require-continue-on-fail](docs/rules/require-continue-on-fail.md) | Require continueOnFail() handling in execute() methods of node classes | ✅ ☑️ | | | | |
| [require-node-api-error](docs/rules/require-node-api-error.md) | Require NodeApiError or NodeOperationError for error wrapping in catch blocks. Raw errors lose HTTP context in the n8n UI. | ✅ ☑️ | | | | |
| [require-node-description-fields](docs/rules/require-node-description-fields.md) | Node class description must define all required fields: icon, subtitle | ✅ ☑️ | | | | |
| [resource-operation-pattern](docs/rules/resource-operation-pattern.md) | Enforce proper resource/operation pattern for better UX in n8n nodes | | ✅ ☑️ | | | |
| [valid-credential-references](docs/rules/valid-credential-references.md) | Ensure credentials referenced in node descriptions exist as credential classes in the package | ✅ ☑️ | | | 💡 | |
| [valid-description](docs/rules/valid-description.md) | Require a non-empty "description" field in community node package.json | ✅ ☑️ | | | | |
| [valid-peer-dependencies](docs/rules/valid-peer-dependencies.md) | Require community node package.json peerDependencies to contain only "n8n-workflow": "*" (and optionally "ai-node-sdk") | ✅ ☑️ | | 🔧 | | |
| [webhook-lifecycle-complete](docs/rules/webhook-lifecycle-complete.md) | Require webhook trigger nodes to implement the complete webhookMethods lifecycle (checkExists, create, delete) | ✅ ☑️ | | | | |
<!-- end auto-generated rules list -->

View File

@ -0,0 +1,38 @@
# Credential `name` field must end with `Api` and start with a lowercase letter (`@n8n/community-nodes/cred-class-name-field-conventions`)
💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
<!-- end auto-generated rule header -->
## Rule Details
The `name` field of a credential class (those implementing `ICredentialType` in `*.credentials.ts` files) is the internal identifier referenced by nodes and stored in the credential registry. n8n convention requires this identifier to:
- End with `Api` (e.g. `githubApi`), so credentials are easily recognisable across the codebase.
- Start with a lowercase letter (camelCase), since it is an identifier value rather than a class name.
Both checks are automatically fixable.
## Examples
### ❌ Incorrect
```typescript
export class GithubApi implements ICredentialType {
name = 'Github';
displayName = 'GitHub API';
properties: INodeProperties[] = [];
}
```
### ✅ Correct
```typescript
export class GithubApi implements ICredentialType {
name = 'githubApi';
displayName = 'GitHub API';
properties: INodeProperties[] = [];
}
```

View File

@ -0,0 +1,38 @@
# Disallow wire-format expression syntax (={{...}}) and NodeConnectionType string literals in builderHint texts and AI-builder prompts. Use expr() and SDK-canonical references instead (`@n8n/community-nodes/no-builder-hint-leakage`)
💼 This rule is enabled in the following configs: ✅ `recommended`, ☑️ `recommendedWithoutN8nCloudSupport`.
<!-- end auto-generated rule header -->
## Rule Details
`builderHint` texts and AI-builder prompts are authored as human-facing guidance, but they sometimes leak n8n's internal wire format:
- Raw expression syntax such as `={{ $json.foo }}`, which only makes sense inside the execution engine.
- `NodeConnectionType` string literals such as `ai_languageModel` or `ai_tool`, which are structured connection identifiers rather than prose.
When these leak into hints and prompts, they confuse the builder experience and the AI assistant. Use the `expr()` SDK helper for expressions and the SDK-canonical reference helpers (e.g. `languageModel()`, `tool()`, `memory()`) instead.
## Options
This rule accepts an options object:
- `scope` (`'builderHint' | 'all'`, default `'builderHint'`) — `builderHint` only scans string values inside `builderHint` property values. `all` scans every string in the file, intended for AI-builder prompt files.
## Examples
### ❌ Incorrect
```typescript
const node = {
builderHint: 'Set the model with ={{ $json.model }} and connect an ai_languageModel.',
};
```
### ✅ Correct
```typescript
const node = {
builderHint: 'Set the model with expr($json.model) and connect a languageModel().',
};
```

View File

@ -17,7 +17,7 @@
"dev": "pnpm watch",
"format": "biome format --write .",
"format:check": "biome ci .",
"lint": "eslint src",
"lint": "eslint src && pnpm lint:docs",
"lint:fix": "eslint src --fix",
"lint:docs": "pnpm build && eslint-doc-generator --check",
"test": "vitest run",
@ -27,6 +27,7 @@
"watch": "tsc --watch --project tsconfig.build.json"
},
"dependencies": {
"@typescript-eslint/typescript-estree": "^8.35.0",
"@typescript-eslint/utils": "^8.35.0",
"fastest-levenshtein": "catalog:"
},

View File

@ -40,6 +40,7 @@ const configs = {
'@n8n/community-nodes/resource-operation-pattern': 'warn',
'@n8n/community-nodes/credential-documentation-url': 'error',
'@n8n/community-nodes/cred-class-field-icon-missing': 'error',
'@n8n/community-nodes/cred-class-name-field-conventions': 'error',
'@n8n/community-nodes/cred-class-name-suffix': 'error',
'@n8n/community-nodes/cred-class-oauth2-naming': 'error',
'@n8n/community-nodes/node-connection-type-literal': 'error',
@ -80,6 +81,7 @@ const configs = {
'@n8n/community-nodes/credential-documentation-url': 'error',
'@n8n/community-nodes/resource-operation-pattern': 'warn',
'@n8n/community-nodes/cred-class-field-icon-missing': 'error',
'@n8n/community-nodes/cred-class-name-field-conventions': 'error',
'@n8n/community-nodes/cred-class-name-suffix': 'error',
'@n8n/community-nodes/cred-class-oauth2-naming': 'error',
'@n8n/community-nodes/node-connection-type-literal': 'error',

View File

@ -0,0 +1,121 @@
import { RuleTester } from '@typescript-eslint/rule-tester';
import { CredClassNameFieldConventionsRule } from './cred-class-name-field-conventions.js';
const ruleTester = new RuleTester();
const credFilePath = '/tmp/TestCredential.credentials.ts';
const nonCredFilePath = '/tmp/SomeHelper.ts';
function createCredentialCode(name: string): string {
return `
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
export class TestApi implements ICredentialType {
name = '${name}';
displayName = 'Test API';
properties: INodeProperties[] = [];
}`;
}
function createRegularClass(name: string): string {
return `
export class SomeHelper {
name = '${name}';
}`;
}
// Embeds the raw literal text (including its quotes) verbatim, so tests can
// exercise names containing quote characters that need escaping.
function createCredentialCodeWithLiteral(literal: string): string {
return `
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
export class TestApi implements ICredentialType {
name = ${literal};
displayName = 'Test API';
properties: INodeProperties[] = [];
}`;
}
ruleTester.run('cred-class-name-field-conventions', CredClassNameFieldConventionsRule, {
valid: [
{
name: 'name field with Api suffix and lowercase first char',
filename: credFilePath,
code: createCredentialCode('githubApi'),
},
{
name: 'OAuth2 name field is also valid',
filename: credFilePath,
code: createCredentialCode('githubOAuth2Api'),
},
{
name: 'class not implementing ICredentialType is ignored',
filename: credFilePath,
code: createRegularClass('Github'),
},
{
name: 'non-.credentials.ts file is ignored',
filename: nonCredFilePath,
code: createCredentialCode('Github'),
},
],
invalid: [
{
name: 'name field missing Api suffix',
filename: credFilePath,
code: createCredentialCode('github'),
errors: [{ messageId: 'missingSuffix', data: { value: 'github' } }],
output: createCredentialCode('githubApi'),
},
{
name: 'name field with uppercase first char',
filename: credFilePath,
code: createCredentialCode('GithubApi'),
errors: [{ messageId: 'uppercaseFirstChar', data: { value: 'GithubApi' } }],
output: createCredentialCode('githubApi'),
},
{
name: 'name field with both uppercase first char and missing suffix',
filename: credFilePath,
code: createCredentialCode('Github'),
errors: [
{ messageId: 'uppercaseFirstChar', data: { value: 'Github' } },
{ messageId: 'missingSuffix', data: { value: 'Github' } },
],
output: createCredentialCode('githubApi'),
},
{
name: 'name field ending in Ap',
filename: credFilePath,
code: createCredentialCode('githubAp'),
errors: [{ messageId: 'missingSuffix', data: { value: 'githubAp' } }],
output: createCredentialCode('githubApi'),
},
{
name: 'name field ending in A',
filename: credFilePath,
code: createCredentialCode('githubA'),
errors: [{ messageId: 'missingSuffix', data: { value: 'githubA' } }],
output: createCredentialCode('githubApi'),
},
{
name: 'autofix escapes single quotes in the name value',
filename: credFilePath,
code: createCredentialCodeWithLiteral("'git\\'hub'"),
errors: [{ messageId: 'missingSuffix', data: { value: "git'hub" } }],
output: createCredentialCodeWithLiteral("'git\\'hubApi'"),
},
{
name: 'autofix preserves double quotes and escapes them in the name value',
filename: credFilePath,
code: createCredentialCodeWithLiteral('"Git\\"hub"'),
errors: [
{ messageId: 'uppercaseFirstChar', data: { value: 'Git"hub' } },
{ messageId: 'missingSuffix', data: { value: 'Git"hub' } },
],
output: createCredentialCodeWithLiteral('"git\\"hubApi"'),
},
],
});

View File

@ -0,0 +1,102 @@
import {
createRule,
findClassProperty,
getStringLiteralValue,
isCredentialTypeClass,
isFileType,
} from '../utils/index.js';
function lowercaseFirstChar(name: string): string {
return name.charAt(0).toLowerCase() + name.slice(1);
}
function addApiSuffix(name: string): string {
if (name.endsWith('Api')) return name;
if (name.endsWith('Ap')) return `${name}i`;
if (name.endsWith('A')) return `${name}pi`;
return `${name}Api`;
}
// Serialize a value as a string literal using the original quote character,
// escaping any characters that would otherwise break the literal so the
// autofix never emits invalid code (e.g. names containing quotes).
function toStringLiteral(value: string, quote: string): string {
const escaped = value
.replace(/\\/g, '\\\\')
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.split(quote)
.join(`\\${quote}`);
return `${quote}${escaped}${quote}`;
}
export const CredClassNameFieldConventionsRule = createRule({
name: 'cred-class-name-field-conventions',
meta: {
type: 'problem',
docs: {
description: 'Credential `name` field must end with `Api` and start with a lowercase letter',
},
messages: {
missingSuffix: "Credential `name` field '{{value}}' must end with 'Api'",
uppercaseFirstChar: "Credential `name` field '{{value}}' must start with a lowercase letter",
},
fixable: 'code',
schema: [],
},
defaultOptions: [],
create(context) {
if (!isFileType(context.filename, '.credentials.ts')) {
return {};
}
return {
ClassDeclaration(node) {
if (!isCredentialTypeClass(node)) {
return;
}
const nameProperty = findClassProperty(node, 'name');
if (!nameProperty?.value) {
return;
}
const nameValue = getStringLiteralValue(nameProperty.value);
if (nameValue === null) {
return;
}
const startsLowercase = !/^[A-Z]/.test(nameValue);
const endsWithApi = nameValue.endsWith('Api');
if (startsLowercase && endsWithApi) {
return;
}
// Compute the fully-corrected value once so each fix yields the
// same result in a single pass, regardless of which one applies.
const fixedValue = addApiSuffix(lowercaseFirstChar(nameValue));
const valueNode = nameProperty.value;
const quote = context.sourceCode.getText(valueNode).charAt(0);
const replacement = toStringLiteral(fixedValue, quote);
if (!startsLowercase) {
context.report({
node: valueNode,
messageId: 'uppercaseFirstChar',
data: { value: nameValue },
fix: (fixer) => fixer.replaceText(valueNode, replacement),
});
}
if (!endsWithApi) {
context.report({
node: valueNode,
messageId: 'missingSuffix',
data: { value: nameValue },
fix: (fixer) => fixer.replaceText(valueNode, replacement),
});
}
},
};
},
});

View File

@ -1,4 +1,4 @@
import { TSESTree } from '@typescript-eslint/types';
import { TSESTree } from '@typescript-eslint/utils';
import type { ReportFixFunction } from '@typescript-eslint/utils/ts-eslint';
import {

View File

@ -2,6 +2,7 @@ import type { AnyRuleModule } from '@typescript-eslint/utils/ts-eslint';
import { AiNodePackageJsonRule } from './ai-node-package-json.js';
import { CredClassFieldIconMissingRule } from './cred-class-field-icon-missing.js';
import { CredClassNameFieldConventionsRule } from './cred-class-name-field-conventions.js';
import { CredClassNameSuffixRule } from './cred-class-name-suffix.js';
import { CredClassOAuth2NamingRule } from './cred-class-oauth2-naming.js';
import { CredentialDocumentationUrlRule } from './credential-documentation-url.js';
@ -57,6 +58,7 @@ export const rules = {
'credential-documentation-url': CredentialDocumentationUrlRule,
'node-class-description-icon-missing': NodeClassDescriptionIconMissingRule,
'cred-class-field-icon-missing': CredClassFieldIconMissingRule,
'cred-class-name-field-conventions': CredClassNameFieldConventionsRule,
'cred-class-name-suffix': CredClassNameSuffixRule,
'cred-class-oauth2-naming': CredClassOAuth2NamingRule,
'node-connection-type-literal': NodeConnectionTypeLiteralRule,

View File

@ -1,4 +1,4 @@
import { TSESTree } from '@typescript-eslint/types';
import { TSESTree } from '@typescript-eslint/utils';
import type { ReportSuggestionArray } from '@typescript-eslint/utils/ts-eslint';
import {

View File

@ -1,4 +1,4 @@
import { TSESTree } from '@typescript-eslint/types';
import { TSESTree } from '@typescript-eslint/utils';
import type { TSESLint } from '@typescript-eslint/utils';
import { createRule } from '../utils/index.js';

View File

@ -1,4 +1,4 @@
import { TSESTree } from '@typescript-eslint/types';
import { TSESTree } from '@typescript-eslint/utils';
import {
isNodeTypeClass,

View File

@ -1,5 +1,4 @@
import { DefinitionType } from '@typescript-eslint/scope-manager';
import { AST_NODE_TYPES, type TSESTree } from '@typescript-eslint/utils';
import { AST_NODE_TYPES, TSESLint, type TSESTree } from '@typescript-eslint/utils';
import { isFileType } from '../utils/index.js';
import { createRule } from '../utils/rule-creator.js';
@ -68,7 +67,9 @@ export const RequireNodeApiErrorRule = createRule({
const scope = context.sourceCode.getScope(node);
const ref = scope.references.find((r) => r.identifier === argument);
const isCatchParam =
ref?.resolved?.defs.some((def) => def.type === DefinitionType.CatchClause) ?? false;
ref?.resolved?.defs.some(
(def) => def.type === TSESLint.Scope.DefinitionType.CatchClause,
) ?? false;
if (isCatchParam) {
context.report({ node, messageId: 'useNodeApiError' });

View File

@ -1,4 +1,4 @@
import { TSESTree } from '@typescript-eslint/types';
import { TSESTree } from '@typescript-eslint/utils';
import type { ReportSuggestionArray } from '@typescript-eslint/utils/ts-eslint';
import {

View File

@ -1643,6 +1643,9 @@ importers:
packages/@n8n/eslint-plugin-community-nodes:
dependencies:
'@typescript-eslint/typescript-estree':
specifier: ^8.35.0
version: 8.35.0(typescript@6.0.2)
'@typescript-eslint/utils':
specifier: ^8.35.0
version: 8.35.0(eslint@9.29.0(jiti@2.6.1))(typescript@6.0.2)