@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.
Files changed (230) hide show
  1. package/README.md +154 -150
  2. package/dist/bin/mule-lint-mcp.js.map +1 -1
  3. package/dist/bin/mule-lint.js +2 -2
  4. package/dist/bin/mule-lint.js.map +1 -1
  5. package/dist/package.json +26 -15
  6. package/dist/src/core/ComplexityCalculator.d.ts.map +1 -1
  7. package/dist/src/core/ComplexityCalculator.js.map +1 -1
  8. package/dist/src/core/FileScanner.d.ts.map +1 -1
  9. package/dist/src/core/FileScanner.js.map +1 -1
  10. package/dist/src/core/MetricsAggregator.d.ts.map +1 -1
  11. package/dist/src/core/MetricsAggregator.js +1 -1
  12. package/dist/src/core/MetricsAggregator.js.map +1 -1
  13. package/dist/src/core/MetricsCollector.d.ts.map +1 -1
  14. package/dist/src/core/MetricsCollector.js +1 -2
  15. package/dist/src/core/MetricsCollector.js.map +1 -1
  16. package/dist/src/core/QualityGateEvaluator.d.ts.map +1 -1
  17. package/dist/src/core/QualityGateEvaluator.js.map +1 -1
  18. package/dist/src/core/XPathHelper.d.ts.map +1 -1
  19. package/dist/src/core/XPathHelper.js +0 -1
  20. package/dist/src/core/XPathHelper.js.map +1 -1
  21. package/dist/src/core/XmlParser.d.ts.map +1 -1
  22. package/dist/src/core/XmlParser.js.map +1 -1
  23. package/dist/src/core/YamlParser.d.ts.map +1 -1
  24. package/dist/src/core/YamlParser.js.map +1 -1
  25. package/dist/src/core/errors.js.map +1 -1
  26. package/dist/src/engine/LintEngine.d.ts.map +1 -1
  27. package/dist/src/engine/LintEngine.js.map +1 -1
  28. package/dist/src/formatter/MuleXmlFormatter.d.ts.map +1 -1
  29. package/dist/src/formatter/MuleXmlFormatter.js +7 -1
  30. package/dist/src/formatter/MuleXmlFormatter.js.map +1 -1
  31. package/dist/src/formatter/index.d.ts +2 -2
  32. package/dist/src/formatter/index.d.ts.map +1 -1
  33. package/dist/src/formatter/index.js.map +1 -1
  34. package/dist/src/formatters/CsvFormatter.js.map +1 -1
  35. package/dist/src/formatters/HtmlFormatter.js +0 -1
  36. package/dist/src/formatters/HtmlFormatter.js.map +1 -1
  37. package/dist/src/formatters/JsonFormatter.d.ts.map +1 -1
  38. package/dist/src/formatters/JsonFormatter.js.map +1 -1
  39. package/dist/src/formatters/SarifFormatter.js.map +1 -1
  40. package/dist/src/formatters/TableFormatter.js.map +1 -1
  41. package/dist/src/formatters/html/components/Icons.js +1 -1
  42. package/dist/src/formatters/html/components/Icons.js.map +1 -1
  43. package/dist/src/formatters/html/components/MetricCard.d.ts.map +1 -1
  44. package/dist/src/formatters/html/components/MetricCard.js.map +1 -1
  45. package/dist/src/formatters/html/components/Modal.d.ts.map +1 -1
  46. package/dist/src/formatters/html/components/Modal.js.map +1 -1
  47. package/dist/src/formatters/html/components/RatingBadge.d.ts.map +1 -1
  48. package/dist/src/formatters/html/components/RatingBadge.js +6 -6
  49. package/dist/src/formatters/html/components/RatingBadge.js.map +1 -1
  50. package/dist/src/formatters/html/index.d.ts +2 -2
  51. package/dist/src/formatters/html/index.d.ts.map +1 -1
  52. package/dist/src/formatters/html/index.js.map +1 -1
  53. package/dist/src/formatters/html/scripts/charts.d.ts.map +1 -1
  54. package/dist/src/formatters/html/scripts/charts.js +45 -12
  55. package/dist/src/formatters/html/scripts/charts.js.map +1 -1
  56. package/dist/src/formatters/html/scripts/index.d.ts.map +1 -1
  57. package/dist/src/formatters/html/scripts/index.js.map +1 -1
  58. package/dist/src/formatters/html/scripts/renderer.d.ts.map +1 -1
  59. package/dist/src/formatters/html/scripts/renderer.js +175 -35
  60. package/dist/src/formatters/html/scripts/renderer.js.map +1 -1
  61. package/dist/src/formatters/html/sections/Header.d.ts.map +1 -1
  62. package/dist/src/formatters/html/sections/Header.js.map +1 -1
  63. package/dist/src/formatters/html/sections/LintSummary.d.ts.map +1 -1
  64. package/dist/src/formatters/html/sections/LintSummary.js.map +1 -1
  65. package/dist/src/formatters/html/sections/QualityRatings.js.map +1 -1
  66. package/dist/src/formatters/html/sections/Sidebar.d.ts.map +1 -1
  67. package/dist/src/formatters/html/sections/Sidebar.js.map +1 -1
  68. package/dist/src/formatters/html/styles/badges.d.ts.map +1 -1
  69. package/dist/src/formatters/html/styles/badges.js.map +1 -1
  70. package/dist/src/formatters/html/styles/index.d.ts.map +1 -1
  71. package/dist/src/formatters/html/styles/index.js.map +1 -1
  72. package/dist/src/formatters/html/theme.js.map +1 -1
  73. package/dist/src/formatters/html/views/Dashboard.js +5 -5
  74. package/dist/src/formatters/html/views/Dashboard.js.map +1 -1
  75. package/dist/src/formatters/html/views/IssuesView.d.ts.map +1 -1
  76. package/dist/src/formatters/html/views/IssuesView.js.map +1 -1
  77. package/dist/src/formatters/index.js.map +1 -1
  78. package/dist/src/mcp/index.d.ts.map +1 -1
  79. package/dist/src/mcp/index.js +0 -1
  80. package/dist/src/mcp/index.js.map +1 -1
  81. package/dist/src/mcp/prompts/index.js.map +1 -1
  82. package/dist/src/mcp/resources/index.js +30 -7
  83. package/dist/src/mcp/resources/index.js.map +1 -1
  84. package/dist/src/mcp/tools/formatMuleXml.d.ts.map +1 -1
  85. package/dist/src/mcp/tools/formatMuleXml.js +4 -13
  86. package/dist/src/mcp/tools/formatMuleXml.js.map +1 -1
  87. package/dist/src/mcp/tools/getRuleDetails.d.ts.map +1 -1
  88. package/dist/src/mcp/tools/getRuleDetails.js +1 -3
  89. package/dist/src/mcp/tools/getRuleDetails.js.map +1 -1
  90. package/dist/src/mcp/tools/runLintAnalysis.js +9 -9
  91. package/dist/src/mcp/tools/runLintAnalysis.js.map +1 -1
  92. package/dist/src/mcp/tools/validateSnippet.d.ts.map +1 -1
  93. package/dist/src/mcp/tools/validateSnippet.js.map +1 -1
  94. package/dist/src/quality/calculator.d.ts.map +1 -1
  95. package/dist/src/quality/calculator.js +1 -1
  96. package/dist/src/quality/calculator.js.map +1 -1
  97. package/dist/src/quality/index.d.ts.map +1 -1
  98. package/dist/src/quality/index.js.map +1 -1
  99. package/dist/src/quality/thresholds.js.map +1 -1
  100. package/dist/src/quality/types.d.ts.map +1 -1
  101. package/dist/src/rules/api-led/ApiLedRules.d.ts.map +1 -1
  102. package/dist/src/rules/api-led/ApiLedRules.js +6 -2
  103. package/dist/src/rules/api-led/ApiLedRules.js.map +1 -1
  104. package/dist/src/rules/api-led/SingleSystemSapiRule.d.ts.map +1 -1
  105. package/dist/src/rules/api-led/SingleSystemSapiRule.js.map +1 -1
  106. package/dist/src/rules/base/BaseRule.d.ts.map +1 -1
  107. package/dist/src/rules/base/BaseRule.js.map +1 -1
  108. package/dist/src/rules/base/ProjectRule.d.ts.map +1 -1
  109. package/dist/src/rules/base/ProjectRule.js.map +1 -1
  110. package/dist/src/rules/complexity/FlowComplexityRule.d.ts.map +1 -1
  111. package/dist/src/rules/complexity/FlowComplexityRule.js.map +1 -1
  112. package/dist/src/rules/dataweave/DataWeaveRules.d.ts.map +1 -1
  113. package/dist/src/rules/dataweave/DataWeaveRules.js +1 -3
  114. package/dist/src/rules/dataweave/DataWeaveRules.js.map +1 -1
  115. package/dist/src/rules/dataweave/Java17DWErrorHandlingRule.d.ts.map +1 -1
  116. package/dist/src/rules/dataweave/Java17DWErrorHandlingRule.js.map +1 -1
  117. package/dist/src/rules/documentation/DisplayNameRule.d.ts.map +1 -1
  118. package/dist/src/rules/documentation/DisplayNameRule.js.map +1 -1
  119. package/dist/src/rules/documentation/FlowDescriptionRule.d.ts.map +1 -1
  120. package/dist/src/rules/documentation/FlowDescriptionRule.js.map +1 -1
  121. package/dist/src/rules/documentation/MissingDocNameRule.d.ts.map +1 -1
  122. package/dist/src/rules/documentation/MissingDocNameRule.js.map +1 -1
  123. package/dist/src/rules/error-handling/CorrelationIdRule.d.ts.map +1 -1
  124. package/dist/src/rules/error-handling/CorrelationIdRule.js.map +1 -1
  125. package/dist/src/rules/error-handling/GenericErrorRule.d.ts.map +1 -1
  126. package/dist/src/rules/error-handling/GenericErrorRule.js.map +1 -1
  127. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts.map +1 -1
  128. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js.map +1 -1
  129. package/dist/src/rules/error-handling/HttpStatusRule.d.ts.map +1 -1
  130. package/dist/src/rules/error-handling/HttpStatusRule.js.map +1 -1
  131. package/dist/src/rules/error-handling/MissingErrorHandlerRule.d.ts.map +1 -1
  132. package/dist/src/rules/error-handling/MissingErrorHandlerRule.js.map +1 -1
  133. package/dist/src/rules/error-handling/TryScopeRule.d.ts.map +1 -1
  134. package/dist/src/rules/error-handling/TryScopeRule.js.map +1 -1
  135. package/dist/src/rules/experimental/ExperimentalRules.d.ts.map +1 -1
  136. package/dist/src/rules/experimental/ExperimentalRules.js +6 -2
  137. package/dist/src/rules/experimental/ExperimentalRules.js.map +1 -1
  138. package/dist/src/rules/governance/GovernanceRules.d.ts.map +1 -1
  139. package/dist/src/rules/governance/GovernanceRules.js.map +1 -1
  140. package/dist/src/rules/http/HttpContentTypeRule.d.ts.map +1 -1
  141. package/dist/src/rules/http/HttpContentTypeRule.js.map +1 -1
  142. package/dist/src/rules/http/HttpTimeoutRule.d.ts.map +1 -1
  143. package/dist/src/rules/http/HttpTimeoutRule.js.map +1 -1
  144. package/dist/src/rules/http/HttpUserAgentRule.d.ts.map +1 -1
  145. package/dist/src/rules/http/HttpUserAgentRule.js.map +1 -1
  146. package/dist/src/rules/index.js.map +1 -1
  147. package/dist/src/rules/logging/ExcessiveLoggersRule.d.ts.map +1 -1
  148. package/dist/src/rules/logging/ExcessiveLoggersRule.js.map +1 -1
  149. package/dist/src/rules/logging/LoggerCategoryRule.d.ts.map +1 -1
  150. package/dist/src/rules/logging/LoggerCategoryRule.js.map +1 -1
  151. package/dist/src/rules/logging/LoggerInUntilSuccessfulRule.d.ts.map +1 -1
  152. package/dist/src/rules/logging/LoggerInUntilSuccessfulRule.js.map +1 -1
  153. package/dist/src/rules/logging/LoggerPayloadRule.d.ts.map +1 -1
  154. package/dist/src/rules/logging/LoggerPayloadRule.js.map +1 -1
  155. package/dist/src/rules/logging/NewLoggingRules.d.ts.map +1 -1
  156. package/dist/src/rules/logging/NewLoggingRules.js.map +1 -1
  157. package/dist/src/rules/naming/FlowCasingRule.d.ts.map +1 -1
  158. package/dist/src/rules/naming/FlowCasingRule.js.map +1 -1
  159. package/dist/src/rules/naming/FlowNamingRule.d.ts.map +1 -1
  160. package/dist/src/rules/naming/FlowNamingRule.js +3 -1
  161. package/dist/src/rules/naming/FlowNamingRule.js.map +1 -1
  162. package/dist/src/rules/naming/VariableNamingRule.d.ts.map +1 -1
  163. package/dist/src/rules/naming/VariableNamingRule.js.map +1 -1
  164. package/dist/src/rules/operations/CommentedCodeRule.d.ts.map +1 -1
  165. package/dist/src/rules/operations/CommentedCodeRule.js.map +1 -1
  166. package/dist/src/rules/operations/UnusedFlowRule.d.ts.map +1 -1
  167. package/dist/src/rules/operations/UnusedFlowRule.js.map +1 -1
  168. package/dist/src/rules/performance/AsyncErrorHandlerRule.d.ts.map +1 -1
  169. package/dist/src/rules/performance/AsyncErrorHandlerRule.js.map +1 -1
  170. package/dist/src/rules/performance/ConnectionPoolingRule.d.ts.map +1 -1
  171. package/dist/src/rules/performance/ConnectionPoolingRule.js.map +1 -1
  172. package/dist/src/rules/performance/LargeChoiceBlockRule.d.ts.map +1 -1
  173. package/dist/src/rules/performance/LargeChoiceBlockRule.js.map +1 -1
  174. package/dist/src/rules/performance/ReconnectionStrategyRule.d.ts.map +1 -1
  175. package/dist/src/rules/performance/ReconnectionStrategyRule.js.map +1 -1
  176. package/dist/src/rules/performance/ScatterGatherRoutesRule.d.ts.map +1 -1
  177. package/dist/src/rules/performance/ScatterGatherRoutesRule.js.map +1 -1
  178. package/dist/src/rules/security/EncryptionKeyInLogsRule.d.ts.map +1 -1
  179. package/dist/src/rules/security/EncryptionKeyInLogsRule.js.map +1 -1
  180. package/dist/src/rules/security/HardcodedCredentialsRule.d.ts.map +1 -1
  181. package/dist/src/rules/security/HardcodedCredentialsRule.js.map +1 -1
  182. package/dist/src/rules/security/HardcodedHttpRule.d.ts.map +1 -1
  183. package/dist/src/rules/security/HardcodedHttpRule.js +1 -9
  184. package/dist/src/rules/security/HardcodedHttpRule.js.map +1 -1
  185. package/dist/src/rules/security/InputValidationRule.d.ts.map +1 -1
  186. package/dist/src/rules/security/InputValidationRule.js +1 -3
  187. package/dist/src/rules/security/InputValidationRule.js.map +1 -1
  188. package/dist/src/rules/security/InsecureTlsRule.d.ts.map +1 -1
  189. package/dist/src/rules/security/InsecureTlsRule.js.map +1 -1
  190. package/dist/src/rules/security/RateLimitingRule.d.ts.map +1 -1
  191. package/dist/src/rules/security/RateLimitingRule.js.map +1 -1
  192. package/dist/src/rules/security/TlsVersionRule.d.ts.map +1 -1
  193. package/dist/src/rules/security/TlsVersionRule.js.map +1 -1
  194. package/dist/src/rules/standards/ApiKitValidationRule.d.ts.map +1 -1
  195. package/dist/src/rules/standards/ApiKitValidationRule.js.map +1 -1
  196. package/dist/src/rules/standards/AutoDiscoveryRule.d.ts.map +1 -1
  197. package/dist/src/rules/standards/AutoDiscoveryRule.js.map +1 -1
  198. package/dist/src/rules/standards/ChoiceAntiPatternRule.d.ts.map +1 -1
  199. package/dist/src/rules/standards/ChoiceAntiPatternRule.js.map +1 -1
  200. package/dist/src/rules/standards/CronExternalizedRule.d.ts.map +1 -1
  201. package/dist/src/rules/standards/CronExternalizedRule.js.map +1 -1
  202. package/dist/src/rules/standards/DeprecatedComponentRule.d.ts.map +1 -1
  203. package/dist/src/rules/standards/DeprecatedComponentRule.js.map +1 -1
  204. package/dist/src/rules/standards/DwlStandardsRule.d.ts.map +1 -1
  205. package/dist/src/rules/standards/DwlStandardsRule.js.map +1 -1
  206. package/dist/src/rules/standards/HttpPortPlaceholderRule.d.ts.map +1 -1
  207. package/dist/src/rules/standards/HttpPortPlaceholderRule.js.map +1 -1
  208. package/dist/src/rules/structure/StructureRules.d.ts.map +1 -1
  209. package/dist/src/rules/structure/StructureRules.js.map +1 -1
  210. package/dist/src/rules/yaml/YamlRules.d.ts.map +1 -1
  211. package/dist/src/rules/yaml/YamlRules.js +2 -7
  212. package/dist/src/rules/yaml/YamlRules.js.map +1 -1
  213. package/dist/src/types/Config.d.ts.map +1 -1
  214. package/dist/src/types/Config.js.map +1 -1
  215. package/dist/src/types/QualityGate.d.ts.map +1 -1
  216. package/dist/src/types/QualityGate.js.map +1 -1
  217. package/dist/src/types/Report.d.ts.map +1 -1
  218. package/dist/src/types/Rule.d.ts.map +1 -1
  219. package/docs/README.md +27 -27
  220. package/docs/best-practices/documentation-standards.md +20 -11
  221. package/docs/best-practices/folder-structure.md +16 -10
  222. package/docs/best-practices/mulesoft-best-practices.md +96 -94
  223. package/docs/best-practices/rules-catalog.md +316 -287
  224. package/docs/linter/architecture.md +70 -64
  225. package/docs/linter/extending.md +137 -128
  226. package/docs/linter/folder-structure.md +39 -38
  227. package/docs/linter/naming-conventions.md +80 -78
  228. package/docs/linter/rule-engine.md +306 -306
  229. package/docs/mcp-design.md +35 -21
  230. 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 | Namespace |
114
- |--------|-----------|
115
- | `mule` | http://www.mulesoft.org/schema/mule/core |
116
- | `http` | http://www.mulesoft.org/schema/mule/http |
117
- | `ee` | http://www.mulesoft.org/schema/mule/ee/core |
118
- | `db` | http://www.mulesoft.org/schema/mule/db |
119
- | `doc` | http://www.mulesoft.org/schema/mule/documentation |
120
- | `tls` | http://www.mulesoft.org/schema/mule/tls |
121
- | `file` | http://www.mulesoft.org/schema/mule/file |
122
- | `sftp` | http://www.mulesoft.org/schema/mule/sftp |
123
- | `vm` | http://www.mulesoft.org/schema/mule/vm |
124
- | `jms` | http://www.mulesoft.org/schema/mule/jms |
125
- | `apikit` | http://www.mulesoft.org/schema/mule/mule-apikit |
126
- | `batch` | http://www.mulesoft.org/schema/mule/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
- id: string;
174
- name: string;
175
- severity: Severity;
176
- validate(doc: Document, context: ValidationContext): Issue[];
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
- switch (type) {
187
- case 'table': return formatTable;
188
- case 'json': return formatJson;
189
- case 'sarif': return formatSarif;
190
- case 'html': return formatHtml;
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 | ID Prefix | Count | Description |
260
- |----------|-----------|-------|-------------|
261
- | Error Handling | MULE-00X | 5 | Error handler presence and configuration |
262
- | Naming | MULE-002, 10X | 3 | Flow, variable, and file naming |
263
- | Security | MULE-004, 20X | 3 | Hardcoded values and security |
264
- | Logging | MULE-006, 30X | 3 | Logger configuration |
265
- | HTTP | MULE-40X | 3 | HTTP request configuration |
266
- | Performance | MULE-50X | 3 | Performance anti-patterns |
267
- | Documentation | MULE-60X | 2 | Component documentation |
268
- | Standards | MULE-008, 010, 70X | 3 | Best practices |
269
- | Complexity | MULE-80X | 1 | Cyclomatic complexity |
270
- | Structure | MULE-80X | 3 | Project structure |
271
- | YAML | YAML-XXX | 3 | Properties validation |
272
- | DataWeave | DW-XXX | 3 | DWL file validation |
273
- | API-Led | API-XXX | 3 | API-Led patterns |
274
- | Experimental | EXP-XXX | 3 | Beta rules |
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 | Target |
300
- |--------|--------|
301
- | Files per second | > 100 |
302
- | Memory per file | < 10MB |
303
- | Rule execution | < 50ms per rule |
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 | No errors or warnings |
311
- | 1 | At least one error found |
312
- | 2 | Configuration error |
313
- | 3 | Critical error (parse failure) |
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) |
@@ -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
- // Required properties
39
- id = 'MULE-103';
40
- name = 'API Naming Convention';
41
- description = 'API implementation flows should follow the pattern: {api-name}-{version}-{operation}';
42
- severity: Severity = 'warning';
43
- category: RuleCategory = 'naming';
44
-
45
- // Optional: Link to documentation
46
- docsUrl = 'https://your-wiki/mule-standards#api-naming';
47
-
48
- validate(doc: Document, context: ValidationContext): Issue[] {
49
- const issues: Issue[] = [];
50
-
51
- // Your XPath query
52
- const flows = this.select('//mule:flow', doc);
53
-
54
- // Pattern for API flows
55
- const apiPattern = /^[\w-]+-v\d+-(?:get|post|put|delete|patch)-[\w-]+$/;
56
-
57
- for (const flow of flows) {
58
- const name = this.getAttribute(flow, 'name');
59
-
60
- // Only check flows that look like API implementations
61
- if (name && name.includes('-api') && !apiPattern.test(name)) {
62
- issues.push(this.createIssue(
63
- flow,
64
- `API flow "${name}" doesn't follow naming convention: {api-name}-v{N}-{method}-{resource}`,
65
- {
66
- suggestion: 'Example: orders-api-v1-get-order-by-id'
67
- }
68
- ));
69
- }
70
- }
71
-
72
- return issues;
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
- // ... existing rules
86
- new ApiNamingRule(),
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
- const rule = new ApiNamingRule();
101
- const context = createMockContext('api.xml');
102
-
103
- it('should pass for correctly named API flow', () => {
104
- const xml = `
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
- const doc = parseXml(xml);
112
- const issues = rule.validate(doc, context);
113
-
114
- expect(issues).toHaveLength(0);
115
- });
116
-
117
- it('should fail for incorrectly named API flow', () => {
118
- const xml = `
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
- const doc = parseXml(xml);
126
- const issues = rule.validate(doc, context);
127
-
128
- expect(issues).toHaveLength(1);
129
- expect(issues[0].ruleId).toBe('MULE-103');
130
- });
131
-
132
- it('should ignore non-API flows', () => {
133
- const xml = `
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
- const doc = parseXml(xml);
141
- const issues = rule.validate(doc, context);
142
-
143
- expect(issues).toHaveLength(0);
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
- | Property | Value |
157
- |----------|-------|
158
- | **ID** | MULE-103 |
159
- | **Severity** | Warning |
160
- | **Category** | Naming |
161
- | **Fixable** | No |
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
- ├── rules/
216
- ├── AcmeLoggingRule.ts
217
- └── AcmeSecurityRule.ts
218
- └── index.ts
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
- id = 'PROJECT-001';
295
- name = 'Project Specific Check';
296
- description = 'Custom check for this project';
297
- severity = 'warning' as const;
298
- category = 'standards' as const;
299
-
300
- validate(doc: Document, context: ValidationContext): Issue[] {
301
- // Your custom logic
302
- return [];
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(this.createIssue(node, message, {
335
- suggestion: 'Add category attribute: category="com.acme.integration"'
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
- private engine: LintEngine;
385
-
386
- constructor() {
387
- this.engine = new LintEngine({
388
- rules: RULES,
389
- // Or filter rules
390
- // rules: RULES.filter(r => r.severity === 'error')
391
- });
392
- }
393
-
394
- async provideDiagnostics(document: vscode.TextDocument): Promise<vscode.Diagnostic[]> {
395
- const issues = await this.engine.scanContent(
396
- document.getText(),
397
- document.uri.fsPath
398
- );
399
-
400
- return issues.map(issue => this.toDiagnostic(issue));
401
- }
402
-
403
- private toDiagnostic(issue: Issue): vscode.Diagnostic {
404
- return new vscode.Diagnostic(
405
- new vscode.Range(issue.line - 1, 0, issue.line - 1, 100),
406
- `[${issue.ruleId}] ${issue.message}`,
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