@sfdxy/mule-lint 1.18.1 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -150
- package/dist/bin/mule-lint-mcp.js.map +1 -1
- package/dist/bin/mule-lint.js +2 -2
- package/dist/bin/mule-lint.js.map +1 -1
- package/dist/package.json +26 -15
- package/dist/src/core/ComplexityCalculator.d.ts.map +1 -1
- package/dist/src/core/ComplexityCalculator.js.map +1 -1
- package/dist/src/core/FileScanner.d.ts.map +1 -1
- package/dist/src/core/FileScanner.js.map +1 -1
- package/dist/src/core/MetricsAggregator.d.ts.map +1 -1
- package/dist/src/core/MetricsAggregator.js +1 -1
- package/dist/src/core/MetricsAggregator.js.map +1 -1
- package/dist/src/core/MetricsCollector.d.ts.map +1 -1
- package/dist/src/core/MetricsCollector.js +1 -2
- package/dist/src/core/MetricsCollector.js.map +1 -1
- package/dist/src/core/QualityGateEvaluator.d.ts.map +1 -1
- package/dist/src/core/QualityGateEvaluator.js.map +1 -1
- package/dist/src/core/XPathHelper.d.ts.map +1 -1
- package/dist/src/core/XPathHelper.js +0 -1
- package/dist/src/core/XPathHelper.js.map +1 -1
- package/dist/src/core/XmlParser.d.ts.map +1 -1
- package/dist/src/core/XmlParser.js.map +1 -1
- package/dist/src/core/YamlParser.d.ts.map +1 -1
- package/dist/src/core/YamlParser.js.map +1 -1
- package/dist/src/core/errors.js.map +1 -1
- package/dist/src/engine/LintEngine.d.ts.map +1 -1
- package/dist/src/engine/LintEngine.js.map +1 -1
- package/dist/src/formatter/MuleXmlFormatter.d.ts.map +1 -1
- package/dist/src/formatter/MuleXmlFormatter.js +7 -1
- package/dist/src/formatter/MuleXmlFormatter.js.map +1 -1
- package/dist/src/formatter/index.d.ts +2 -2
- package/dist/src/formatter/index.d.ts.map +1 -1
- package/dist/src/formatter/index.js.map +1 -1
- package/dist/src/formatters/CsvFormatter.js.map +1 -1
- package/dist/src/formatters/HtmlFormatter.js +0 -1
- package/dist/src/formatters/HtmlFormatter.js.map +1 -1
- package/dist/src/formatters/JsonFormatter.d.ts.map +1 -1
- package/dist/src/formatters/JsonFormatter.js.map +1 -1
- package/dist/src/formatters/SarifFormatter.js.map +1 -1
- package/dist/src/formatters/TableFormatter.js.map +1 -1
- package/dist/src/formatters/html/components/Icons.js +1 -1
- package/dist/src/formatters/html/components/Icons.js.map +1 -1
- package/dist/src/formatters/html/components/MetricCard.d.ts.map +1 -1
- package/dist/src/formatters/html/components/MetricCard.js.map +1 -1
- package/dist/src/formatters/html/components/Modal.d.ts.map +1 -1
- package/dist/src/formatters/html/components/Modal.js.map +1 -1
- package/dist/src/formatters/html/components/RatingBadge.d.ts.map +1 -1
- package/dist/src/formatters/html/components/RatingBadge.js +6 -6
- package/dist/src/formatters/html/components/RatingBadge.js.map +1 -1
- package/dist/src/formatters/html/index.d.ts +2 -2
- package/dist/src/formatters/html/index.d.ts.map +1 -1
- package/dist/src/formatters/html/index.js.map +1 -1
- package/dist/src/formatters/html/scripts/charts.d.ts.map +1 -1
- package/dist/src/formatters/html/scripts/charts.js +45 -12
- package/dist/src/formatters/html/scripts/charts.js.map +1 -1
- package/dist/src/formatters/html/scripts/index.d.ts.map +1 -1
- package/dist/src/formatters/html/scripts/index.js.map +1 -1
- package/dist/src/formatters/html/scripts/renderer.d.ts.map +1 -1
- package/dist/src/formatters/html/scripts/renderer.js +175 -35
- package/dist/src/formatters/html/scripts/renderer.js.map +1 -1
- package/dist/src/formatters/html/sections/Header.d.ts.map +1 -1
- package/dist/src/formatters/html/sections/Header.js.map +1 -1
- package/dist/src/formatters/html/sections/LintSummary.d.ts.map +1 -1
- package/dist/src/formatters/html/sections/LintSummary.js.map +1 -1
- package/dist/src/formatters/html/sections/QualityRatings.js.map +1 -1
- package/dist/src/formatters/html/sections/Sidebar.d.ts.map +1 -1
- package/dist/src/formatters/html/sections/Sidebar.js.map +1 -1
- package/dist/src/formatters/html/styles/badges.d.ts.map +1 -1
- package/dist/src/formatters/html/styles/badges.js.map +1 -1
- package/dist/src/formatters/html/styles/index.d.ts.map +1 -1
- package/dist/src/formatters/html/styles/index.js.map +1 -1
- package/dist/src/formatters/html/theme.js.map +1 -1
- package/dist/src/formatters/html/views/Dashboard.js +5 -5
- package/dist/src/formatters/html/views/Dashboard.js.map +1 -1
- package/dist/src/formatters/html/views/IssuesView.d.ts.map +1 -1
- package/dist/src/formatters/html/views/IssuesView.js.map +1 -1
- package/dist/src/formatters/index.js.map +1 -1
- package/dist/src/mcp/index.d.ts.map +1 -1
- package/dist/src/mcp/index.js +0 -1
- package/dist/src/mcp/index.js.map +1 -1
- package/dist/src/mcp/prompts/index.js.map +1 -1
- package/dist/src/mcp/resources/index.js +30 -7
- package/dist/src/mcp/resources/index.js.map +1 -1
- package/dist/src/mcp/tools/formatMuleXml.d.ts.map +1 -1
- package/dist/src/mcp/tools/formatMuleXml.js +4 -13
- package/dist/src/mcp/tools/formatMuleXml.js.map +1 -1
- package/dist/src/mcp/tools/getRuleDetails.d.ts.map +1 -1
- package/dist/src/mcp/tools/getRuleDetails.js +1 -3
- package/dist/src/mcp/tools/getRuleDetails.js.map +1 -1
- package/dist/src/mcp/tools/runLintAnalysis.js +9 -9
- package/dist/src/mcp/tools/runLintAnalysis.js.map +1 -1
- package/dist/src/mcp/tools/validateSnippet.d.ts.map +1 -1
- package/dist/src/mcp/tools/validateSnippet.js.map +1 -1
- package/dist/src/quality/calculator.d.ts.map +1 -1
- package/dist/src/quality/calculator.js +1 -1
- package/dist/src/quality/calculator.js.map +1 -1
- package/dist/src/quality/index.d.ts.map +1 -1
- package/dist/src/quality/index.js.map +1 -1
- package/dist/src/quality/thresholds.js.map +1 -1
- package/dist/src/quality/types.d.ts.map +1 -1
- package/dist/src/rules/api-led/ApiLedRules.d.ts.map +1 -1
- package/dist/src/rules/api-led/ApiLedRules.js +6 -2
- package/dist/src/rules/api-led/ApiLedRules.js.map +1 -1
- package/dist/src/rules/api-led/SingleSystemSapiRule.d.ts.map +1 -1
- package/dist/src/rules/api-led/SingleSystemSapiRule.js.map +1 -1
- package/dist/src/rules/base/BaseRule.d.ts.map +1 -1
- package/dist/src/rules/base/BaseRule.js.map +1 -1
- package/dist/src/rules/base/ProjectRule.d.ts.map +1 -1
- package/dist/src/rules/base/ProjectRule.js.map +1 -1
- package/dist/src/rules/complexity/FlowComplexityRule.d.ts.map +1 -1
- package/dist/src/rules/complexity/FlowComplexityRule.js.map +1 -1
- package/dist/src/rules/dataweave/DataWeaveRules.d.ts.map +1 -1
- package/dist/src/rules/dataweave/DataWeaveRules.js +1 -3
- package/dist/src/rules/dataweave/DataWeaveRules.js.map +1 -1
- package/dist/src/rules/dataweave/Java17DWErrorHandlingRule.d.ts.map +1 -1
- package/dist/src/rules/dataweave/Java17DWErrorHandlingRule.js.map +1 -1
- package/dist/src/rules/documentation/DisplayNameRule.d.ts.map +1 -1
- package/dist/src/rules/documentation/DisplayNameRule.js.map +1 -1
- package/dist/src/rules/documentation/FlowDescriptionRule.d.ts.map +1 -1
- package/dist/src/rules/documentation/FlowDescriptionRule.js.map +1 -1
- package/dist/src/rules/documentation/MissingDocNameRule.d.ts.map +1 -1
- package/dist/src/rules/documentation/MissingDocNameRule.js.map +1 -1
- package/dist/src/rules/error-handling/CorrelationIdRule.d.ts.map +1 -1
- package/dist/src/rules/error-handling/CorrelationIdRule.js.map +1 -1
- package/dist/src/rules/error-handling/GenericErrorRule.d.ts.map +1 -1
- package/dist/src/rules/error-handling/GenericErrorRule.js.map +1 -1
- package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts.map +1 -1
- package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js.map +1 -1
- package/dist/src/rules/error-handling/HttpStatusRule.d.ts.map +1 -1
- package/dist/src/rules/error-handling/HttpStatusRule.js.map +1 -1
- package/dist/src/rules/error-handling/MissingErrorHandlerRule.d.ts.map +1 -1
- package/dist/src/rules/error-handling/MissingErrorHandlerRule.js.map +1 -1
- package/dist/src/rules/error-handling/TryScopeRule.d.ts.map +1 -1
- package/dist/src/rules/error-handling/TryScopeRule.js.map +1 -1
- package/dist/src/rules/experimental/ExperimentalRules.d.ts.map +1 -1
- package/dist/src/rules/experimental/ExperimentalRules.js +6 -2
- package/dist/src/rules/experimental/ExperimentalRules.js.map +1 -1
- package/dist/src/rules/governance/GovernanceRules.d.ts.map +1 -1
- package/dist/src/rules/governance/GovernanceRules.js.map +1 -1
- package/dist/src/rules/http/HttpContentTypeRule.d.ts.map +1 -1
- package/dist/src/rules/http/HttpContentTypeRule.js.map +1 -1
- package/dist/src/rules/http/HttpTimeoutRule.d.ts.map +1 -1
- package/dist/src/rules/http/HttpTimeoutRule.js.map +1 -1
- package/dist/src/rules/http/HttpUserAgentRule.d.ts.map +1 -1
- package/dist/src/rules/http/HttpUserAgentRule.js.map +1 -1
- package/dist/src/rules/index.js.map +1 -1
- package/dist/src/rules/logging/ExcessiveLoggersRule.d.ts.map +1 -1
- package/dist/src/rules/logging/ExcessiveLoggersRule.js.map +1 -1
- package/dist/src/rules/logging/LoggerCategoryRule.d.ts.map +1 -1
- package/dist/src/rules/logging/LoggerCategoryRule.js.map +1 -1
- package/dist/src/rules/logging/LoggerInUntilSuccessfulRule.d.ts.map +1 -1
- package/dist/src/rules/logging/LoggerInUntilSuccessfulRule.js.map +1 -1
- package/dist/src/rules/logging/LoggerPayloadRule.d.ts.map +1 -1
- package/dist/src/rules/logging/LoggerPayloadRule.js.map +1 -1
- package/dist/src/rules/logging/NewLoggingRules.d.ts.map +1 -1
- package/dist/src/rules/logging/NewLoggingRules.js.map +1 -1
- package/dist/src/rules/naming/FlowCasingRule.d.ts.map +1 -1
- package/dist/src/rules/naming/FlowCasingRule.js.map +1 -1
- package/dist/src/rules/naming/FlowNamingRule.d.ts.map +1 -1
- package/dist/src/rules/naming/FlowNamingRule.js +3 -1
- package/dist/src/rules/naming/FlowNamingRule.js.map +1 -1
- package/dist/src/rules/naming/VariableNamingRule.d.ts.map +1 -1
- package/dist/src/rules/naming/VariableNamingRule.js.map +1 -1
- package/dist/src/rules/operations/CommentedCodeRule.d.ts.map +1 -1
- package/dist/src/rules/operations/CommentedCodeRule.js.map +1 -1
- package/dist/src/rules/operations/UnusedFlowRule.d.ts.map +1 -1
- package/dist/src/rules/operations/UnusedFlowRule.js.map +1 -1
- package/dist/src/rules/performance/AsyncErrorHandlerRule.d.ts.map +1 -1
- package/dist/src/rules/performance/AsyncErrorHandlerRule.js.map +1 -1
- package/dist/src/rules/performance/ConnectionPoolingRule.d.ts.map +1 -1
- package/dist/src/rules/performance/ConnectionPoolingRule.js.map +1 -1
- package/dist/src/rules/performance/LargeChoiceBlockRule.d.ts.map +1 -1
- package/dist/src/rules/performance/LargeChoiceBlockRule.js.map +1 -1
- package/dist/src/rules/performance/ReconnectionStrategyRule.d.ts.map +1 -1
- package/dist/src/rules/performance/ReconnectionStrategyRule.js.map +1 -1
- package/dist/src/rules/performance/ScatterGatherRoutesRule.d.ts.map +1 -1
- package/dist/src/rules/performance/ScatterGatherRoutesRule.js.map +1 -1
- package/dist/src/rules/security/EncryptionKeyInLogsRule.d.ts.map +1 -1
- package/dist/src/rules/security/EncryptionKeyInLogsRule.js.map +1 -1
- package/dist/src/rules/security/HardcodedCredentialsRule.d.ts.map +1 -1
- package/dist/src/rules/security/HardcodedCredentialsRule.js.map +1 -1
- package/dist/src/rules/security/HardcodedHttpRule.d.ts.map +1 -1
- package/dist/src/rules/security/HardcodedHttpRule.js +1 -9
- package/dist/src/rules/security/HardcodedHttpRule.js.map +1 -1
- package/dist/src/rules/security/InputValidationRule.d.ts.map +1 -1
- package/dist/src/rules/security/InputValidationRule.js +1 -3
- package/dist/src/rules/security/InputValidationRule.js.map +1 -1
- package/dist/src/rules/security/InsecureTlsRule.d.ts.map +1 -1
- package/dist/src/rules/security/InsecureTlsRule.js.map +1 -1
- package/dist/src/rules/security/RateLimitingRule.d.ts.map +1 -1
- package/dist/src/rules/security/RateLimitingRule.js.map +1 -1
- package/dist/src/rules/security/TlsVersionRule.d.ts.map +1 -1
- package/dist/src/rules/security/TlsVersionRule.js.map +1 -1
- package/dist/src/rules/standards/ApiKitValidationRule.d.ts.map +1 -1
- package/dist/src/rules/standards/ApiKitValidationRule.js.map +1 -1
- package/dist/src/rules/standards/AutoDiscoveryRule.d.ts.map +1 -1
- package/dist/src/rules/standards/AutoDiscoveryRule.js.map +1 -1
- package/dist/src/rules/standards/ChoiceAntiPatternRule.d.ts.map +1 -1
- package/dist/src/rules/standards/ChoiceAntiPatternRule.js.map +1 -1
- package/dist/src/rules/standards/CronExternalizedRule.d.ts.map +1 -1
- package/dist/src/rules/standards/CronExternalizedRule.js.map +1 -1
- package/dist/src/rules/standards/DeprecatedComponentRule.d.ts.map +1 -1
- package/dist/src/rules/standards/DeprecatedComponentRule.js.map +1 -1
- package/dist/src/rules/standards/DwlStandardsRule.d.ts.map +1 -1
- package/dist/src/rules/standards/DwlStandardsRule.js.map +1 -1
- package/dist/src/rules/standards/HttpPortPlaceholderRule.d.ts.map +1 -1
- package/dist/src/rules/standards/HttpPortPlaceholderRule.js.map +1 -1
- package/dist/src/rules/structure/StructureRules.d.ts.map +1 -1
- package/dist/src/rules/structure/StructureRules.js.map +1 -1
- package/dist/src/rules/yaml/YamlRules.d.ts.map +1 -1
- package/dist/src/rules/yaml/YamlRules.js +2 -7
- package/dist/src/rules/yaml/YamlRules.js.map +1 -1
- package/dist/src/types/Config.d.ts.map +1 -1
- package/dist/src/types/Config.js.map +1 -1
- package/dist/src/types/QualityGate.d.ts.map +1 -1
- package/dist/src/types/QualityGate.js.map +1 -1
- package/dist/src/types/Report.d.ts.map +1 -1
- package/dist/src/types/Rule.d.ts.map +1 -1
- package/docs/README.md +27 -27
- package/docs/best-practices/documentation-standards.md +20 -11
- package/docs/best-practices/folder-structure.md +16 -10
- package/docs/best-practices/mulesoft-best-practices.md +96 -94
- package/docs/best-practices/rules-catalog.md +316 -287
- package/docs/linter/architecture.md +70 -64
- package/docs/linter/extending.md +137 -128
- package/docs/linter/folder-structure.md +39 -38
- package/docs/linter/naming-conventions.md +80 -78
- package/docs/linter/rule-engine.md +306 -306
- package/docs/mcp-design.md +35 -21
- package/package.json +84 -73
|
@@ -9,14 +9,14 @@ flowchart TB
|
|
|
9
9
|
subgraph CLI["CLI Layer (commander)"]
|
|
10
10
|
A["mule-lint ./path -f sarif"]
|
|
11
11
|
end
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
subgraph Engine["LintEngine"]
|
|
14
14
|
B[FileScanner<br/>fast-glob] --> C[XmlParser<br/>xmldom]
|
|
15
15
|
C --> D[Rule Executor]
|
|
16
16
|
B --> E[YamlParser<br/>yaml]
|
|
17
17
|
E --> D
|
|
18
18
|
end
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
subgraph Rules["Rules (56 Total)"]
|
|
21
21
|
D --> R1[Error Handling<br/>MULE-001,003,005,007,009]
|
|
22
22
|
D --> R2[Naming<br/>MULE-002,101,102]
|
|
@@ -33,14 +33,14 @@ flowchart TB
|
|
|
33
33
|
D --> R13[API-Led<br/>API-001,002,003]
|
|
34
34
|
D --> R14[Experimental<br/>EXP-001,002,003]
|
|
35
35
|
end
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
subgraph Output["Formatters"]
|
|
38
38
|
J[Table<br/>Human]
|
|
39
39
|
K[JSON<br/>Scripts]
|
|
40
40
|
L[SARIF<br/>AI Agents]
|
|
41
41
|
M[HTML<br/>Reports]
|
|
42
42
|
end
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
A --> B
|
|
45
45
|
D --> J
|
|
46
46
|
D --> K
|
|
@@ -59,27 +59,27 @@ sequenceDiagram
|
|
|
59
59
|
participant YAML as YamlParser
|
|
60
60
|
participant Rules
|
|
61
61
|
participant Formatter
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
CLI->>Engine: scan(path)
|
|
64
64
|
Engine->>Scanner: scanDirectory(path)
|
|
65
65
|
Scanner-->>Engine: ScannedFile[]
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
loop Each XML File
|
|
68
68
|
Engine->>Parser: parseXml(content)
|
|
69
69
|
Parser-->>Engine: Document
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
loop Each Rule
|
|
72
72
|
Engine->>Rules: validate(doc, context)
|
|
73
73
|
Rules-->>Engine: Issue[]
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
loop YAML Rules
|
|
78
78
|
Engine->>YAML: parseYaml(path)
|
|
79
79
|
YAML-->>Engine: Properties
|
|
80
80
|
Engine->>Rules: validate(props, context)
|
|
81
81
|
end
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
Engine->>Formatter: format(report)
|
|
84
84
|
Formatter-->>CLI: string output
|
|
85
85
|
```
|
|
@@ -89,6 +89,7 @@ sequenceDiagram
|
|
|
89
89
|
### LintEngine
|
|
90
90
|
|
|
91
91
|
The central orchestrator that:
|
|
92
|
+
|
|
92
93
|
1. Scans directories for XML and YAML files using FileScanner
|
|
93
94
|
2. Parses each file with XmlParser or YamlParser
|
|
94
95
|
3. Executes all enabled rules against each document
|
|
@@ -110,20 +111,20 @@ const flows = xpath.selectNodes('//mule:flow', document);
|
|
|
110
111
|
|
|
111
112
|
Pre-configured namespaces:
|
|
112
113
|
|
|
113
|
-
| Prefix
|
|
114
|
-
|
|
115
|
-
| `mule`
|
|
116
|
-
| `http`
|
|
117
|
-
| `ee`
|
|
118
|
-
| `db`
|
|
119
|
-
| `doc`
|
|
120
|
-
| `tls`
|
|
121
|
-
| `file`
|
|
122
|
-
| `sftp`
|
|
123
|
-
| `vm`
|
|
124
|
-
| `jms`
|
|
125
|
-
| `apikit` | http://www.mulesoft.org/schema/mule/mule-apikit
|
|
126
|
-
| `batch`
|
|
114
|
+
| Prefix | Namespace |
|
|
115
|
+
| -------- | ------------------------------------------------- |
|
|
116
|
+
| `mule` | http://www.mulesoft.org/schema/mule/core |
|
|
117
|
+
| `http` | http://www.mulesoft.org/schema/mule/http |
|
|
118
|
+
| `ee` | http://www.mulesoft.org/schema/mule/ee/core |
|
|
119
|
+
| `db` | http://www.mulesoft.org/schema/mule/db |
|
|
120
|
+
| `doc` | http://www.mulesoft.org/schema/mule/documentation |
|
|
121
|
+
| `tls` | http://www.mulesoft.org/schema/mule/tls |
|
|
122
|
+
| `file` | http://www.mulesoft.org/schema/mule/file |
|
|
123
|
+
| `sftp` | http://www.mulesoft.org/schema/mule/sftp |
|
|
124
|
+
| `vm` | http://www.mulesoft.org/schema/mule/vm |
|
|
125
|
+
| `jms` | http://www.mulesoft.org/schema/mule/jms |
|
|
126
|
+
| `apikit` | http://www.mulesoft.org/schema/mule/mule-apikit |
|
|
127
|
+
| `batch` | http://www.mulesoft.org/schema/mule/batch |
|
|
127
128
|
|
|
128
129
|
### BaseRule
|
|
129
130
|
|
|
@@ -143,21 +144,22 @@ classDiagram
|
|
|
143
144
|
#createIssue(node, message): Issue
|
|
144
145
|
#getOption(context, key, default): T
|
|
145
146
|
}
|
|
146
|
-
|
|
147
|
+
|
|
147
148
|
class FlowNamingRule {
|
|
148
149
|
+validate()
|
|
149
150
|
}
|
|
150
|
-
|
|
151
|
+
|
|
151
152
|
class YamlRuleBase {
|
|
152
153
|
+validate()
|
|
153
154
|
#findYamlFiles(): string[]
|
|
154
155
|
}
|
|
155
|
-
|
|
156
|
+
|
|
156
157
|
BaseRule <|-- FlowNamingRule
|
|
157
158
|
BaseRule <|-- YamlRuleBase
|
|
158
159
|
```
|
|
159
160
|
|
|
160
161
|
**Issue Types for Quality Metrics:**
|
|
162
|
+
|
|
161
163
|
- `code-smell` (default) - Maintainability issues
|
|
162
164
|
- `bug` - Reliability issues (error-handling rules)
|
|
163
165
|
- `vulnerability` - Security issues (security rules)
|
|
@@ -170,10 +172,10 @@ Each rule is a strategy implementing the same interface:
|
|
|
170
172
|
|
|
171
173
|
```typescript
|
|
172
174
|
interface Rule {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
id: string;
|
|
176
|
+
name: string;
|
|
177
|
+
severity: Severity;
|
|
178
|
+
validate(doc: Document, context: ValidationContext): Issue[];
|
|
177
179
|
}
|
|
178
180
|
```
|
|
179
181
|
|
|
@@ -183,12 +185,16 @@ Formatters are selected via factory function:
|
|
|
183
185
|
|
|
184
186
|
```typescript
|
|
185
187
|
function getFormatter(type: FormatterType): Formatter {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
188
|
+
switch (type) {
|
|
189
|
+
case 'table':
|
|
190
|
+
return formatTable;
|
|
191
|
+
case 'json':
|
|
192
|
+
return formatJson;
|
|
193
|
+
case 'sarif':
|
|
194
|
+
return formatSarif;
|
|
195
|
+
case 'html':
|
|
196
|
+
return formatHtml;
|
|
197
|
+
}
|
|
192
198
|
}
|
|
193
199
|
```
|
|
194
200
|
|
|
@@ -256,22 +262,22 @@ src/
|
|
|
256
262
|
|
|
257
263
|
## Rule Categories
|
|
258
264
|
|
|
259
|
-
| Category
|
|
260
|
-
|
|
261
|
-
| Error Handling | MULE-00X
|
|
262
|
-
| Naming
|
|
263
|
-
| Security
|
|
264
|
-
| Logging
|
|
265
|
-
| HTTP
|
|
266
|
-
| Performance
|
|
267
|
-
| Documentation
|
|
268
|
-
| Standards
|
|
269
|
-
| Complexity
|
|
270
|
-
| Structure
|
|
271
|
-
| YAML
|
|
272
|
-
| DataWeave
|
|
273
|
-
| API-Led
|
|
274
|
-
| Experimental
|
|
265
|
+
| Category | ID Prefix | Count | Description |
|
|
266
|
+
| -------------- | ------------------ | ----- | ---------------------------------------- |
|
|
267
|
+
| Error Handling | MULE-00X | 5 | Error handler presence and configuration |
|
|
268
|
+
| Naming | MULE-002, 10X | 3 | Flow, variable, and file naming |
|
|
269
|
+
| Security | MULE-004, 20X | 3 | Hardcoded values and security |
|
|
270
|
+
| Logging | MULE-006, 30X | 3 | Logger configuration |
|
|
271
|
+
| HTTP | MULE-40X | 3 | HTTP request configuration |
|
|
272
|
+
| Performance | MULE-50X | 3 | Performance anti-patterns |
|
|
273
|
+
| Documentation | MULE-60X | 2 | Component documentation |
|
|
274
|
+
| Standards | MULE-008, 010, 70X | 3 | Best practices |
|
|
275
|
+
| Complexity | MULE-80X | 1 | Cyclomatic complexity |
|
|
276
|
+
| Structure | MULE-80X | 3 | Project structure |
|
|
277
|
+
| YAML | YAML-XXX | 3 | Properties validation |
|
|
278
|
+
| DataWeave | DW-XXX | 3 | DWL file validation |
|
|
279
|
+
| API-Led | API-XXX | 3 | API-Led patterns |
|
|
280
|
+
| Experimental | EXP-XXX | 3 | Beta rules |
|
|
275
281
|
|
|
276
282
|
## Extension Points
|
|
277
283
|
|
|
@@ -296,18 +302,18 @@ src/
|
|
|
296
302
|
|
|
297
303
|
## Performance Specifications
|
|
298
304
|
|
|
299
|
-
| Metric
|
|
300
|
-
|
|
301
|
-
| Files per second
|
|
302
|
-
| Memory per file
|
|
303
|
-
| Rule execution
|
|
304
|
-
| Total for 100 files | < 5 seconds
|
|
305
|
+
| Metric | Target |
|
|
306
|
+
| ------------------- | --------------- |
|
|
307
|
+
| Files per second | > 100 |
|
|
308
|
+
| Memory per file | < 10MB |
|
|
309
|
+
| Rule execution | < 50ms per rule |
|
|
310
|
+
| Total for 100 files | < 5 seconds |
|
|
305
311
|
|
|
306
312
|
## Exit Codes
|
|
307
313
|
|
|
308
|
-
| Code | Meaning
|
|
309
|
-
|
|
310
|
-
| 0
|
|
311
|
-
| 1
|
|
312
|
-
| 2
|
|
313
|
-
| 3
|
|
314
|
+
| Code | Meaning |
|
|
315
|
+
| ---- | ------------------------------ |
|
|
316
|
+
| 0 | No errors or warnings |
|
|
317
|
+
| 1 | At least one error found |
|
|
318
|
+
| 2 | Configuration error |
|
|
319
|
+
| 3 | Critical error (parse failure) |
|
package/docs/linter/extending.md
CHANGED
|
@@ -35,42 +35,45 @@ import { Document, Node } from '@xmldom/xmldom';
|
|
|
35
35
|
import { BaseRule, Issue, ValidationContext, Severity, RuleCategory } from '@types';
|
|
36
36
|
|
|
37
37
|
export class ApiNamingRule extends BaseRule {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
38
|
+
// Required properties
|
|
39
|
+
id = 'MULE-103';
|
|
40
|
+
name = 'API Naming Convention';
|
|
41
|
+
description =
|
|
42
|
+
'API implementation flows should follow the pattern: {api-name}-{version}-{operation}';
|
|
43
|
+
severity: Severity = 'warning';
|
|
44
|
+
category: RuleCategory = 'naming';
|
|
45
|
+
|
|
46
|
+
// Optional: Link to documentation
|
|
47
|
+
docsUrl = 'https://your-wiki/mule-standards#api-naming';
|
|
48
|
+
|
|
49
|
+
validate(doc: Document, context: ValidationContext): Issue[] {
|
|
50
|
+
const issues: Issue[] = [];
|
|
51
|
+
|
|
52
|
+
// Your XPath query
|
|
53
|
+
const flows = this.select('//mule:flow', doc);
|
|
54
|
+
|
|
55
|
+
// Pattern for API flows
|
|
56
|
+
const apiPattern = /^[\w-]+-v\d+-(?:get|post|put|delete|patch)-[\w-]+$/;
|
|
57
|
+
|
|
58
|
+
for (const flow of flows) {
|
|
59
|
+
const name = this.getAttribute(flow, 'name');
|
|
60
|
+
|
|
61
|
+
// Only check flows that look like API implementations
|
|
62
|
+
if (name && name.includes('-api') && !apiPattern.test(name)) {
|
|
63
|
+
issues.push(
|
|
64
|
+
this.createIssue(
|
|
65
|
+
flow,
|
|
66
|
+
`API flow "${name}" doesn't follow naming convention: {api-name}-v{N}-{method}-{resource}`,
|
|
67
|
+
{
|
|
68
|
+
suggestion: 'Example: orders-api-v1-get-order-by-id',
|
|
69
|
+
},
|
|
70
|
+
),
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
return issues;
|
|
76
|
+
}
|
|
74
77
|
}
|
|
75
78
|
```
|
|
76
79
|
|
|
@@ -82,8 +85,8 @@ Add to `src/rules/index.ts`:
|
|
|
82
85
|
import { ApiNamingRule } from './naming/ApiNamingRule';
|
|
83
86
|
|
|
84
87
|
export const RULES: Rule[] = [
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
// ... existing rules
|
|
89
|
+
new ApiNamingRule(),
|
|
87
90
|
];
|
|
88
91
|
```
|
|
89
92
|
|
|
@@ -97,51 +100,51 @@ import { parseXml } from '../../../src/core/XmlParser';
|
|
|
97
100
|
import { createMockContext } from '../../helpers';
|
|
98
101
|
|
|
99
102
|
describe('ApiNamingRule', () => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
const rule = new ApiNamingRule();
|
|
104
|
+
const context = createMockContext('api.xml');
|
|
105
|
+
|
|
106
|
+
it('should pass for correctly named API flow', () => {
|
|
107
|
+
const xml = `
|
|
105
108
|
<mule xmlns="http://www.mulesoft.org/schema/mule/core">
|
|
106
109
|
<flow name="orders-api-v1-get-order-by-id">
|
|
107
110
|
<logger message="test"/>
|
|
108
111
|
</flow>
|
|
109
112
|
</mule>
|
|
110
113
|
`;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
114
|
+
const doc = parseXml(xml);
|
|
115
|
+
const issues = rule.validate(doc, context);
|
|
116
|
+
|
|
117
|
+
expect(issues).toHaveLength(0);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should fail for incorrectly named API flow', () => {
|
|
121
|
+
const xml = `
|
|
119
122
|
<mule xmlns="http://www.mulesoft.org/schema/mule/core">
|
|
120
123
|
<flow name="orders-api-getOrders">
|
|
121
124
|
<logger message="test"/>
|
|
122
125
|
</flow>
|
|
123
126
|
</mule>
|
|
124
127
|
`;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
const doc = parseXml(xml);
|
|
129
|
+
const issues = rule.validate(doc, context);
|
|
130
|
+
|
|
131
|
+
expect(issues).toHaveLength(1);
|
|
132
|
+
expect(issues[0].ruleId).toBe('MULE-103');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should ignore non-API flows', () => {
|
|
136
|
+
const xml = `
|
|
134
137
|
<mule xmlns="http://www.mulesoft.org/schema/mule/core">
|
|
135
138
|
<flow name="utility-flow">
|
|
136
139
|
<logger message="test"/>
|
|
137
140
|
</flow>
|
|
138
141
|
</mule>
|
|
139
142
|
`;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
const doc = parseXml(xml);
|
|
144
|
+
const issues = rule.validate(doc, context);
|
|
145
|
+
|
|
146
|
+
expect(issues).toHaveLength(0);
|
|
147
|
+
});
|
|
145
148
|
});
|
|
146
149
|
```
|
|
147
150
|
|
|
@@ -153,20 +156,24 @@ Create `docs/rules/MULE-103.md`:
|
|
|
153
156
|
# MULE-103: API Naming Convention
|
|
154
157
|
|
|
155
158
|
## Overview
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
|
159
|
-
| **
|
|
160
|
-
| **
|
|
161
|
-
| **
|
|
159
|
+
|
|
160
|
+
| Property | Value |
|
|
161
|
+
| ------------ | -------- |
|
|
162
|
+
| **ID** | MULE-103 |
|
|
163
|
+
| **Severity** | Warning |
|
|
164
|
+
| **Category** | Naming |
|
|
165
|
+
| **Fixable** | No |
|
|
162
166
|
|
|
163
167
|
## Description
|
|
168
|
+
|
|
164
169
|
API implementation flows should follow a consistent naming pattern that includes the API name, version, HTTP method, and resource.
|
|
165
170
|
|
|
166
171
|
## Pattern
|
|
167
172
|
```
|
|
173
|
+
|
|
168
174
|
{api-name}-v{version}-{method}-{resource}
|
|
169
|
-
|
|
175
|
+
|
|
176
|
+
````
|
|
170
177
|
|
|
171
178
|
## Examples
|
|
172
179
|
|
|
@@ -175,9 +182,10 @@ API implementation flows should follow a consistent naming pattern that includes
|
|
|
175
182
|
<flow name="orders-api-getOrders">
|
|
176
183
|
<flow name="OrdersGetFlow">
|
|
177
184
|
<flow name="get-orders">
|
|
178
|
-
|
|
185
|
+
````
|
|
179
186
|
|
|
180
187
|
### ✅ Good
|
|
188
|
+
|
|
181
189
|
```xml
|
|
182
190
|
<flow name="orders-api-v1-get-orders">
|
|
183
191
|
<flow name="orders-api-v1-post-order">
|
|
@@ -185,6 +193,7 @@ API implementation flows should follow a consistent naming pattern that includes
|
|
|
185
193
|
```
|
|
186
194
|
|
|
187
195
|
## Configuration
|
|
196
|
+
|
|
188
197
|
```json
|
|
189
198
|
{
|
|
190
199
|
"MULE-103": {
|
|
@@ -197,8 +206,10 @@ API implementation flows should follow a consistent naming pattern that includes
|
|
|
197
206
|
```
|
|
198
207
|
|
|
199
208
|
## Related Rules
|
|
209
|
+
|
|
200
210
|
- MULE-002: Flow Naming Convention
|
|
201
211
|
- MULE-101: Flow Name Casing
|
|
212
|
+
|
|
202
213
|
```
|
|
203
214
|
|
|
204
215
|
---
|
|
@@ -210,15 +221,17 @@ For organization-specific rules, create a separate npm package:
|
|
|
210
221
|
### Package Structure
|
|
211
222
|
|
|
212
223
|
```
|
|
224
|
+
|
|
213
225
|
mule-lint-rules-acme/
|
|
214
226
|
├── src/
|
|
215
|
-
│
|
|
216
|
-
│
|
|
217
|
-
│
|
|
218
|
-
│
|
|
227
|
+
│ ├── rules/
|
|
228
|
+
│ │ ├── AcmeLoggingRule.ts
|
|
229
|
+
│ │ └── AcmeSecurityRule.ts
|
|
230
|
+
│ └── index.ts
|
|
219
231
|
├── package.json
|
|
220
232
|
└── tsconfig.json
|
|
221
|
-
|
|
233
|
+
|
|
234
|
+
````
|
|
222
235
|
|
|
223
236
|
### package.json
|
|
224
237
|
|
|
@@ -233,7 +246,7 @@ mule-lint-rules-acme/
|
|
|
233
246
|
},
|
|
234
247
|
"keywords": ["mule-lint", "mule-lint-rules"]
|
|
235
248
|
}
|
|
236
|
-
|
|
249
|
+
````
|
|
237
250
|
|
|
238
251
|
### Export Rules
|
|
239
252
|
|
|
@@ -243,10 +256,7 @@ import { Rule } from 'mule-lint';
|
|
|
243
256
|
import { AcmeLoggingRule } from './rules/AcmeLoggingRule';
|
|
244
257
|
import { AcmeSecurityRule } from './rules/AcmeSecurityRule';
|
|
245
258
|
|
|
246
|
-
export const rules: Rule[] = [
|
|
247
|
-
new AcmeLoggingRule(),
|
|
248
|
-
new AcmeSecurityRule(),
|
|
249
|
-
];
|
|
259
|
+
export const rules: Rule[] = [new AcmeLoggingRule(), new AcmeSecurityRule()];
|
|
250
260
|
|
|
251
261
|
// Named exports for individual rules
|
|
252
262
|
export { AcmeLoggingRule, AcmeSecurityRule };
|
|
@@ -291,16 +301,16 @@ import { BaseRule, Issue, ValidationContext } from 'mule-lint';
|
|
|
291
301
|
import { Document } from '@xmldom/xmldom';
|
|
292
302
|
|
|
293
303
|
export class ProjectSpecificRule extends BaseRule {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
+
id = 'PROJECT-001';
|
|
305
|
+
name = 'Project Specific Check';
|
|
306
|
+
description = 'Custom check for this project';
|
|
307
|
+
severity = 'warning' as const;
|
|
308
|
+
category = 'standards' as const;
|
|
309
|
+
|
|
310
|
+
validate(doc: Document, context: ValidationContext): Issue[] {
|
|
311
|
+
// Your custom logic
|
|
312
|
+
return [];
|
|
313
|
+
}
|
|
304
314
|
}
|
|
305
315
|
```
|
|
306
316
|
|
|
@@ -322,18 +332,20 @@ const nodes = this.select('//http:request[@url]', doc);
|
|
|
322
332
|
|
|
323
333
|
```typescript
|
|
324
334
|
// ❌ Vague
|
|
325
|
-
message: 'Naming violation detected'
|
|
335
|
+
message: 'Naming violation detected';
|
|
326
336
|
|
|
327
337
|
// ✅ Specific and actionable
|
|
328
|
-
message: `Flow "${name}" should end with "-flow". Rename to "${name}-flow"
|
|
338
|
+
message: `Flow "${name}" should end with "-flow". Rename to "${name}-flow"`;
|
|
329
339
|
```
|
|
330
340
|
|
|
331
341
|
### 3. Include Suggestions
|
|
332
342
|
|
|
333
343
|
```typescript
|
|
334
|
-
issues.push(
|
|
335
|
-
|
|
336
|
-
|
|
344
|
+
issues.push(
|
|
345
|
+
this.createIssue(node, message, {
|
|
346
|
+
suggestion: 'Add category attribute: category="com.acme.integration"',
|
|
347
|
+
}),
|
|
348
|
+
);
|
|
337
349
|
```
|
|
338
350
|
|
|
339
351
|
### 4. Support Configuration
|
|
@@ -342,7 +354,7 @@ issues.push(this.createIssue(node, message, {
|
|
|
342
354
|
validate(doc: Document, context: ValidationContext): Issue[] {
|
|
343
355
|
// Read from rule config
|
|
344
356
|
const suffix = context.config.options?.flowSuffix ?? '-flow';
|
|
345
|
-
|
|
357
|
+
|
|
346
358
|
// Use in validation
|
|
347
359
|
if (!name.endsWith(suffix)) {
|
|
348
360
|
// ...
|
|
@@ -355,16 +367,16 @@ validate(doc: Document, context: ValidationContext): Issue[] {
|
|
|
355
367
|
```typescript
|
|
356
368
|
validate(doc: Document, context: ValidationContext): Issue[] {
|
|
357
369
|
const flows = this.select('//mule:flow', doc);
|
|
358
|
-
|
|
370
|
+
|
|
359
371
|
for (const flow of flows) {
|
|
360
372
|
const name = this.getAttribute(flow, 'name');
|
|
361
|
-
|
|
373
|
+
|
|
362
374
|
// Guard against missing attributes
|
|
363
375
|
if (!name) continue;
|
|
364
|
-
|
|
376
|
+
|
|
365
377
|
// Skip excluded patterns
|
|
366
378
|
if (this.isExcluded(name, context)) continue;
|
|
367
|
-
|
|
379
|
+
|
|
368
380
|
// Actual validation
|
|
369
381
|
// ...
|
|
370
382
|
}
|
|
@@ -381,32 +393,29 @@ When building a VS Code extension, import rules directly:
|
|
|
381
393
|
import { LintEngine, RULES, Rule, Issue } from 'mule-lint';
|
|
382
394
|
|
|
383
395
|
class MuleLintDiagnosticProvider {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
this.toSeverity(issue.severity)
|
|
408
|
-
);
|
|
409
|
-
}
|
|
396
|
+
private engine: LintEngine;
|
|
397
|
+
|
|
398
|
+
constructor() {
|
|
399
|
+
this.engine = new LintEngine({
|
|
400
|
+
rules: RULES,
|
|
401
|
+
// Or filter rules
|
|
402
|
+
// rules: RULES.filter(r => r.severity === 'error')
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
async provideDiagnostics(document: vscode.TextDocument): Promise<vscode.Diagnostic[]> {
|
|
407
|
+
const issues = await this.engine.scanContent(document.getText(), document.uri.fsPath);
|
|
408
|
+
|
|
409
|
+
return issues.map((issue) => this.toDiagnostic(issue));
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
private toDiagnostic(issue: Issue): vscode.Diagnostic {
|
|
413
|
+
return new vscode.Diagnostic(
|
|
414
|
+
new vscode.Range(issue.line - 1, 0, issue.line - 1, 100),
|
|
415
|
+
`[${issue.ruleId}] ${issue.message}`,
|
|
416
|
+
this.toSeverity(issue.severity),
|
|
417
|
+
);
|
|
418
|
+
}
|
|
410
419
|
}
|
|
411
420
|
```
|
|
412
421
|
|