@sfdxy/mule-lint 1.20.0 → 1.22.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 (156) hide show
  1. package/README.md +63 -17
  2. package/dist/package.json +1 -1
  3. package/dist/src/core/XPathHelper.d.ts.map +1 -1
  4. package/dist/src/core/XPathHelper.js +8 -0
  5. package/dist/src/core/XPathHelper.js.map +1 -1
  6. package/dist/src/engine/LintEngine.d.ts +22 -0
  7. package/dist/src/engine/LintEngine.d.ts.map +1 -1
  8. package/dist/src/engine/LintEngine.js +105 -18
  9. package/dist/src/engine/LintEngine.js.map +1 -1
  10. package/dist/src/mcp/prompts/index.d.ts +1 -1
  11. package/dist/src/mcp/prompts/index.d.ts.map +1 -1
  12. package/dist/src/mcp/prompts/index.js +62 -1
  13. package/dist/src/mcp/prompts/index.js.map +1 -1
  14. package/dist/src/mcp/resources/index.js +114 -16
  15. package/dist/src/mcp/resources/index.js.map +1 -1
  16. package/dist/src/mcp/tools/getRuleDetails.d.ts.map +1 -1
  17. package/dist/src/mcp/tools/getRuleDetails.js +30 -1
  18. package/dist/src/mcp/tools/getRuleDetails.js.map +1 -1
  19. package/dist/src/rules/api-led/ApikitConsoleProductionRule.d.ts +22 -0
  20. package/dist/src/rules/api-led/ApikitConsoleProductionRule.d.ts.map +1 -0
  21. package/dist/src/rules/api-led/ApikitConsoleProductionRule.js +43 -0
  22. package/dist/src/rules/api-led/ApikitConsoleProductionRule.js.map +1 -0
  23. package/dist/src/rules/api-led/ApikitMainFlowStructureRule.d.ts +24 -0
  24. package/dist/src/rules/api-led/ApikitMainFlowStructureRule.d.ts.map +1 -0
  25. package/dist/src/rules/api-led/ApikitMainFlowStructureRule.js +53 -0
  26. package/dist/src/rules/api-led/ApikitMainFlowStructureRule.js.map +1 -0
  27. package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.d.ts +25 -0
  28. package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.d.ts.map +1 -0
  29. package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.js +59 -0
  30. package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.js.map +1 -0
  31. package/dist/src/rules/connector/EventListenerNullGuardRule.d.ts +24 -0
  32. package/dist/src/rules/connector/EventListenerNullGuardRule.d.ts.map +1 -0
  33. package/dist/src/rules/connector/EventListenerNullGuardRule.js +58 -0
  34. package/dist/src/rules/connector/EventListenerNullGuardRule.js.map +1 -0
  35. package/dist/src/rules/connector/ReplayChannelConfigRule.d.ts +23 -0
  36. package/dist/src/rules/connector/ReplayChannelConfigRule.d.ts.map +1 -0
  37. package/dist/src/rules/connector/ReplayChannelConfigRule.js +52 -0
  38. package/dist/src/rules/connector/ReplayChannelConfigRule.js.map +1 -0
  39. package/dist/src/rules/dataweave/DataWeaveRules.d.ts +11 -4
  40. package/dist/src/rules/dataweave/DataWeaveRules.d.ts.map +1 -1
  41. package/dist/src/rules/dataweave/DataWeaveRules.js +20 -20
  42. package/dist/src/rules/dataweave/DataWeaveRules.js.map +1 -1
  43. package/dist/src/rules/dataweave/DuplicateTransformLogicRule.d.ts +25 -0
  44. package/dist/src/rules/dataweave/DuplicateTransformLogicRule.d.ts.map +1 -0
  45. package/dist/src/rules/dataweave/DuplicateTransformLogicRule.js +63 -0
  46. package/dist/src/rules/dataweave/DuplicateTransformLogicRule.js.map +1 -0
  47. package/dist/src/rules/error-handling/CatchAllLastRule.d.ts +24 -0
  48. package/dist/src/rules/error-handling/CatchAllLastRule.d.ts.map +1 -0
  49. package/dist/src/rules/error-handling/CatchAllLastRule.js +65 -0
  50. package/dist/src/rules/error-handling/CatchAllLastRule.js.map +1 -0
  51. package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.d.ts +28 -0
  52. package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.d.ts.map +1 -0
  53. package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.js +70 -0
  54. package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.js.map +1 -0
  55. package/dist/src/rules/error-handling/ErrorResponseStructureRule.d.ts +23 -0
  56. package/dist/src/rules/error-handling/ErrorResponseStructureRule.d.ts.map +1 -0
  57. package/dist/src/rules/error-handling/ErrorResponseStructureRule.js +73 -0
  58. package/dist/src/rules/error-handling/ErrorResponseStructureRule.js.map +1 -0
  59. package/dist/src/rules/error-handling/GenericErrorRule.d.ts +15 -3
  60. package/dist/src/rules/error-handling/GenericErrorRule.d.ts.map +1 -1
  61. package/dist/src/rules/error-handling/GenericErrorRule.js +58 -18
  62. package/dist/src/rules/error-handling/GenericErrorRule.js.map +1 -1
  63. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts +14 -15
  64. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts.map +1 -1
  65. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js +59 -38
  66. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js.map +1 -1
  67. package/dist/src/rules/error-handling/TryScopeRule.d.ts +5 -0
  68. package/dist/src/rules/error-handling/TryScopeRule.d.ts.map +1 -1
  69. package/dist/src/rules/error-handling/TryScopeRule.js +30 -7
  70. package/dist/src/rules/error-handling/TryScopeRule.js.map +1 -1
  71. package/dist/src/rules/http/ConnectionIdleTimeoutRule.d.ts +27 -0
  72. package/dist/src/rules/http/ConnectionIdleTimeoutRule.d.ts.map +1 -0
  73. package/dist/src/rules/http/ConnectionIdleTimeoutRule.js +46 -0
  74. package/dist/src/rules/http/ConnectionIdleTimeoutRule.js.map +1 -0
  75. package/dist/src/rules/index.d.ts +1 -1
  76. package/dist/src/rules/index.d.ts.map +1 -1
  77. package/dist/src/rules/index.js +50 -8
  78. package/dist/src/rules/index.js.map +1 -1
  79. package/dist/src/rules/logging/LoggerPayloadRule.d.ts +15 -0
  80. package/dist/src/rules/logging/LoggerPayloadRule.d.ts.map +1 -1
  81. package/dist/src/rules/logging/LoggerPayloadRule.js +48 -4
  82. package/dist/src/rules/logging/LoggerPayloadRule.js.map +1 -1
  83. package/dist/src/rules/operations/FlowRefTargetExistsRule.d.ts +23 -0
  84. package/dist/src/rules/operations/FlowRefTargetExistsRule.d.ts.map +1 -0
  85. package/dist/src/rules/operations/FlowRefTargetExistsRule.js +58 -0
  86. package/dist/src/rules/operations/FlowRefTargetExistsRule.js.map +1 -0
  87. package/dist/src/rules/operations/UnusedFlowRule.d.ts +20 -0
  88. package/dist/src/rules/operations/UnusedFlowRule.d.ts.map +1 -1
  89. package/dist/src/rules/operations/UnusedFlowRule.js +73 -7
  90. package/dist/src/rules/operations/UnusedFlowRule.js.map +1 -1
  91. package/dist/src/rules/operations/UnusedVariableRule.d.ts +31 -0
  92. package/dist/src/rules/operations/UnusedVariableRule.d.ts.map +1 -0
  93. package/dist/src/rules/operations/UnusedVariableRule.js +103 -0
  94. package/dist/src/rules/operations/UnusedVariableRule.js.map +1 -0
  95. package/dist/src/rules/performance/ListenerReconnectForeverRule.d.ts +28 -0
  96. package/dist/src/rules/performance/ListenerReconnectForeverRule.d.ts.map +1 -0
  97. package/dist/src/rules/performance/ListenerReconnectForeverRule.js +56 -0
  98. package/dist/src/rules/performance/ListenerReconnectForeverRule.js.map +1 -0
  99. package/dist/src/rules/performance/ReconnectionStrategyRule.d.ts +7 -4
  100. package/dist/src/rules/performance/ReconnectionStrategyRule.d.ts.map +1 -1
  101. package/dist/src/rules/performance/ReconnectionStrategyRule.js +44 -24
  102. package/dist/src/rules/performance/ReconnectionStrategyRule.js.map +1 -1
  103. package/dist/src/rules/security/ConnectorCredentialsSecuredRule.d.ts +36 -0
  104. package/dist/src/rules/security/ConnectorCredentialsSecuredRule.d.ts.map +1 -0
  105. package/dist/src/rules/security/ConnectorCredentialsSecuredRule.js +124 -0
  106. package/dist/src/rules/security/ConnectorCredentialsSecuredRule.js.map +1 -0
  107. package/dist/src/rules/security/HardcodedCredentialsRule.d.ts +4 -0
  108. package/dist/src/rules/security/HardcodedCredentialsRule.d.ts.map +1 -1
  109. package/dist/src/rules/security/HardcodedCredentialsRule.js +15 -0
  110. package/dist/src/rules/security/HardcodedCredentialsRule.js.map +1 -1
  111. package/dist/src/rules/security/SecurePropertiesEncryptionRule.d.ts +25 -0
  112. package/dist/src/rules/security/SecurePropertiesEncryptionRule.d.ts.map +1 -0
  113. package/dist/src/rules/security/SecurePropertiesEncryptionRule.js +59 -0
  114. package/dist/src/rules/security/SecurePropertiesEncryptionRule.js.map +1 -0
  115. package/dist/src/rules/security/SecurePropertiesKeyRule.d.ts +23 -0
  116. package/dist/src/rules/security/SecurePropertiesKeyRule.d.ts.map +1 -0
  117. package/dist/src/rules/security/SecurePropertiesKeyRule.js +45 -0
  118. package/dist/src/rules/security/SecurePropertiesKeyRule.js.map +1 -0
  119. package/dist/src/rules/security/TlsKeystorePasswordRule.d.ts +25 -0
  120. package/dist/src/rules/security/TlsKeystorePasswordRule.d.ts.map +1 -0
  121. package/dist/src/rules/security/TlsKeystorePasswordRule.js +63 -0
  122. package/dist/src/rules/security/TlsKeystorePasswordRule.js.map +1 -0
  123. package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.d.ts +26 -0
  124. package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.d.ts.map +1 -0
  125. package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.js +61 -0
  126. package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.js.map +1 -0
  127. package/dist/src/rules/standards/ConfigPropertiesOrderingRule.d.ts +34 -0
  128. package/dist/src/rules/standards/ConfigPropertiesOrderingRule.d.ts.map +1 -0
  129. package/dist/src/rules/standards/ConfigPropertiesOrderingRule.js +76 -0
  130. package/dist/src/rules/standards/ConfigPropertiesOrderingRule.js.map +1 -0
  131. package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.d.ts +25 -0
  132. package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.d.ts.map +1 -0
  133. package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.js +111 -0
  134. package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.js.map +1 -0
  135. package/dist/src/rules/yaml/YamlRules.d.ts +6 -2
  136. package/dist/src/rules/yaml/YamlRules.d.ts.map +1 -1
  137. package/dist/src/rules/yaml/YamlRules.js +15 -11
  138. package/dist/src/rules/yaml/YamlRules.js.map +1 -1
  139. package/dist/src/types/Rule.d.ts +13 -0
  140. package/dist/src/types/Rule.d.ts.map +1 -1
  141. package/docs/README.md +87 -27
  142. package/docs/best-practices/ci-cd.md +135 -0
  143. package/docs/best-practices/connector-patterns.md +253 -0
  144. package/docs/best-practices/dataweave-patterns.md +370 -0
  145. package/docs/best-practices/deployment-2026.md +171 -0
  146. package/docs/best-practices/error-handling.md +277 -0
  147. package/docs/best-practices/event-driven-patterns.md +424 -0
  148. package/docs/best-practices/logging.md +163 -0
  149. package/docs/best-practices/mulesoft-best-practices.md +72 -865
  150. package/docs/best-practices/performance.md +273 -0
  151. package/docs/best-practices/rules-catalog.md +337 -29
  152. package/docs/best-practices/security.md +181 -0
  153. package/docs/best-practices/testing.md +190 -0
  154. package/docs/best-practices/variable-contracts.md +191 -0
  155. package/docs/linter/architecture.md +119 -64
  156. package/package.json +1 -1
@@ -76,68 +76,166 @@ function registerRulesResource(server) {
76
76
  }
77
77
  /**
78
78
  * Resource: mule-lint://docs/{slug}
79
- * Access official MuleSoft development best practices documentation
79
+ * Access official MuleSoft development best practices documentation.
80
+ *
81
+ * Each slug maps to a focused, self-contained guide optimized for LLM consumption.
82
+ * Guides are typically < 200 lines and cover a single topic with decision matrices,
83
+ * code examples, anti-patterns, and checklists.
80
84
  */
81
85
  function registerDocsResource(server) {
82
86
  server.registerResource('docs', new mcp_js_1.ResourceTemplate('mule-lint://docs/{slug}', {
83
87
  list: () => {
84
88
  return {
85
89
  resources: [
90
+ // ── Core Development ──
86
91
  {
87
- uri: 'mule-lint://docs/architecture',
88
- name: 'Architecture',
92
+ uri: 'mule-lint://docs/error-handling',
93
+ name: 'Error Handling',
94
+ description: 'Global error handlers, HTTP vs event-driven patterns, connector error types, centralized CRM error log objects, self-healing error flows',
89
95
  mimeType: 'text/markdown',
90
96
  },
91
97
  {
92
- uri: 'mule-lint://docs/best-practices',
93
- name: 'Best Practices',
98
+ uri: 'mule-lint://docs/variables',
99
+ name: 'Variable Contracts',
100
+ description: 'Standard variable sets for APIKit routes and event listeners, correlation ID sourcing, array mirroring',
94
101
  mimeType: 'text/markdown',
95
102
  },
96
103
  {
97
- uri: 'mule-lint://docs/documentation-standards',
98
- name: 'Documentation Standards',
104
+ uri: 'mule-lint://docs/logging',
105
+ name: 'Logging Standards',
106
+ description: 'Logger categories, structured JSON logging, MDC/tracing module, PII prevention, log levels',
107
+ mimeType: 'text/markdown',
108
+ },
109
+ {
110
+ uri: 'mule-lint://docs/security',
111
+ name: 'Security',
112
+ description: 'Secure properties, TLS 1.2+, credential management, zero-trust architecture, input validation',
113
+ mimeType: 'text/markdown',
114
+ },
115
+ {
116
+ uri: 'mule-lint://docs/performance',
117
+ name: 'Performance',
118
+ description: 'Timeouts, connection pooling, async error handling, streaming, flow complexity limits, pre-batch bulk lookup (N+1 prevention with scatter-gather + groupBy)',
119
+ mimeType: 'text/markdown',
120
+ },
121
+ // ── Architecture & Patterns ──
122
+ {
123
+ uri: 'mule-lint://docs/event-driven',
124
+ name: 'Event-Driven Patterns',
125
+ description: 'Platform Events, Anypoint MQ, VM Queue Dispatcher, scheduler watermarking with ObjectStore, deferred task polling, AsyncAPI 2.6, deduplication',
99
126
  mimeType: 'text/markdown',
100
127
  },
101
- { uri: 'mule-lint://docs/extending', name: 'Extending', mimeType: 'text/markdown' },
128
+ {
129
+ uri: 'mule-lint://docs/connectors',
130
+ name: 'Connector Patterns',
131
+ description: 'Entity config YAML pattern, Salesforce/NetSuite connector gotchas, protocol negotiation, ObjectStore caching, DWL utility modules',
132
+ mimeType: 'text/markdown',
133
+ },
134
+ {
135
+ uri: 'mule-lint://docs/dataweave',
136
+ name: 'DataWeave Patterns',
137
+ description: 'DWL modules, type coercion for connectors, cross-system value mapping (4 strategies: DWL, JSON dictionary, bidirectional, external), import path rules',
138
+ mimeType: 'text/markdown',
139
+ },
140
+ // ── Project & Operations ──
102
141
  {
103
142
  uri: 'mule-lint://docs/folder-structure',
104
143
  name: 'Folder Structure',
144
+ description: 'Standard Maven layout for Mule 4 projects, file naming, directory organization',
105
145
  mimeType: 'text/markdown',
106
146
  },
107
147
  {
108
- uri: 'mule-lint://docs/naming',
109
- name: 'Naming Conventions',
148
+ uri: 'mule-lint://docs/documentation-standards',
149
+ name: 'Documentation Standards',
150
+ description: 'Flow doc:description, README templates, DataWeave comments, commit message conventions',
151
+ mimeType: 'text/markdown',
152
+ },
153
+ {
154
+ uri: 'mule-lint://docs/testing',
155
+ name: 'Testing (MUnit)',
156
+ description: 'MUnit test structure, error scenario testing, event-driven testing, coverage goals',
157
+ mimeType: 'text/markdown',
158
+ },
159
+ {
160
+ uri: 'mule-lint://docs/ci-cd',
161
+ name: 'CI/CD Integration',
162
+ description: 'Pipeline stages, mule-lint integration, quality gates, SARIF output, GitHub Actions',
163
+ mimeType: 'text/markdown',
164
+ },
165
+ {
166
+ uri: 'mule-lint://docs/deployment',
167
+ name: 'Deployment & Modernization (2026)',
168
+ description: 'CloudHub 2.0, Java 17 migration, Anypoint Code Builder, API Governance, monitoring',
169
+ mimeType: 'text/markdown',
170
+ },
171
+ // ── Reference ──
172
+ {
173
+ uri: 'mule-lint://docs/best-practices',
174
+ name: 'Best Practices Index',
175
+ description: 'Master index linking to all topic-specific guides with quick reference card and API-Led overview',
110
176
  mimeType: 'text/markdown',
111
177
  },
112
178
  {
113
179
  uri: 'mule-lint://docs/rules-catalog',
114
180
  name: 'Rules Catalog',
181
+ description: 'Complete reference for all 82 lint rules with severity, examples, and configuration options',
182
+ mimeType: 'text/markdown',
183
+ },
184
+ // ── Linter Internals (for contributors) ──
185
+ {
186
+ uri: 'mule-lint://docs/architecture',
187
+ name: 'Linter Architecture',
188
+ description: 'Internal linter design, patterns, and data flow (for contributors)',
189
+ mimeType: 'text/markdown',
190
+ },
191
+ {
192
+ uri: 'mule-lint://docs/extending',
193
+ name: 'Extending the Linter',
194
+ description: 'How to create custom rules and extend mule-lint (for contributors)',
115
195
  mimeType: 'text/markdown',
116
196
  },
117
197
  ],
118
198
  };
119
199
  },
120
200
  }), {
121
- description: 'Access the official MuleSoft development best practices and internal documentation. Read these documents to ensure your generated code aligns with our architectural standards, naming conventions, and project structure.',
201
+ description: 'Access MuleSoft development best practices and linter documentation. Each slug maps to a focused topic guide. Start by listing available resources, then read the guides relevant to your current task. For example, read "error-handling" when implementing error handlers, or "connectors" when configuring Salesforce/NetSuite connectors.',
122
202
  mimeType: 'text/markdown',
123
203
  }, (uri, variables) => {
124
204
  const slug = variables.slug;
205
+ // Map slugs to file paths — topic-specific best practices + linter docs
125
206
  const docsMap = {
126
- architecture: 'docs/linter/architecture.md',
127
- 'best-practices': 'docs/best-practices/mulesoft-best-practices.md',
207
+ // Core Development
208
+ 'error-handling': 'docs/best-practices/error-handling.md',
209
+ variables: 'docs/best-practices/variable-contracts.md',
210
+ logging: 'docs/best-practices/logging.md',
211
+ security: 'docs/best-practices/security.md',
212
+ performance: 'docs/best-practices/performance.md',
213
+ // Architecture & Patterns
214
+ 'event-driven': 'docs/best-practices/event-driven-patterns.md',
215
+ connectors: 'docs/best-practices/connector-patterns.md',
216
+ dataweave: 'docs/best-practices/dataweave-patterns.md',
217
+ // Project & Operations
218
+ 'folder-structure': 'docs/best-practices/folder-structure.md',
128
219
  'documentation-standards': 'docs/best-practices/documentation-standards.md',
220
+ testing: 'docs/best-practices/testing.md',
221
+ 'ci-cd': 'docs/best-practices/ci-cd.md',
222
+ deployment: 'docs/best-practices/deployment-2026.md',
223
+ // Reference
224
+ 'best-practices': 'docs/best-practices/mulesoft-best-practices.md',
225
+ 'rules-catalog': 'docs/best-practices/rules-catalog.md',
226
+ // Linter Internals — keep for contributors
227
+ architecture: 'docs/linter/architecture.md',
129
228
  extending: 'docs/linter/extending.md',
130
- 'folder-structure': 'docs/best-practices/folder-structure.md',
131
229
  naming: 'docs/linter/naming-conventions.md',
132
- 'rules-catalog': 'docs/best-practices/rules-catalog.md',
133
230
  };
134
231
  const relativePath = docsMap[slug];
135
232
  if (!relativePath) {
233
+ const available = Object.keys(docsMap).join(', ');
136
234
  return {
137
235
  contents: [
138
236
  {
139
237
  uri: uri.href,
140
- text: `Document not found: ${slug}. Available: ${Object.keys(docsMap).join(', ')}`,
238
+ text: `Document not found: "${slug}". Available slugs: ${available}`,
141
239
  mimeType: 'text/plain',
142
240
  },
143
241
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/mcp/resources/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/mcp/resources/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"getRuleDetails.d.ts","sourceRoot":"","sources":["../../../../src/mcp/tools/getRuleDetails.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4C9D"}
1
+ {"version":3,"file":"getRuleDetails.d.ts","sourceRoot":"","sources":["../../../../src/mcp/tools/getRuleDetails.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4BpE;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAmD9D"}
@@ -3,12 +3,35 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registerGetRuleDetails = registerGetRuleDetails;
4
4
  const zod_1 = require("zod");
5
5
  const rules_1 = require("../../rules");
6
+ /**
7
+ * Mapping from rule category to the best-practice doc slug.
8
+ * Used by get_rule_details to point agents at the relevant guide.
9
+ */
10
+ const categoryToDocSlug = {
11
+ 'error-handling': 'error-handling',
12
+ naming: 'variables',
13
+ security: 'security',
14
+ logging: 'logging',
15
+ http: 'performance',
16
+ performance: 'performance',
17
+ documentation: 'documentation-standards',
18
+ standards: 'best-practices',
19
+ complexity: 'performance',
20
+ structure: 'folder-structure',
21
+ yaml: 'security',
22
+ dataweave: 'dataweave',
23
+ 'api-led': 'best-practices',
24
+ connector: 'connectors',
25
+ governance: 'ci-cd',
26
+ operations: 'ci-cd',
27
+ experimental: 'best-practices',
28
+ };
6
29
  /**
7
30
  * Register the get_rule_details tool on the MCP server
8
31
  */
9
32
  function registerGetRuleDetails(server) {
10
33
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- MCP SDK generic type inference exceeds TS depth limits (TS2589)
11
- server.tool('get_rule_details', 'Retrieve detailed documentation for a specific linting rule ID (e.g., MULE-001). Use this to understand WHY a rule failed and HOW to fix it properly according to best practices.', {
34
+ server.tool('get_rule_details', 'Retrieve detailed documentation for a specific linting rule ID (e.g., MULE-001). Use this to understand WHY a rule failed and HOW to fix it properly according to best practices. Returns rule metadata, the relevant best-practice guide slug, and related rules.', {
12
35
  ruleId: zod_1.z.string().describe('The ID of the rule to retrieve (e.g., "MULE-001", "DW-004")'),
13
36
  }, ({ ruleId }) => {
14
37
  const rule = (0, rules_1.getRuleById)(ruleId);
@@ -23,6 +46,7 @@ function registerGetRuleDetails(server) {
23
46
  isError: true,
24
47
  };
25
48
  }
49
+ const docSlug = categoryToDocSlug[rule.category] || 'best-practices';
26
50
  return {
27
51
  content: [
28
52
  {
@@ -35,6 +59,11 @@ function registerGetRuleDetails(server) {
35
59
  severity: rule.severity,
36
60
  issueType: rule.issueType ?? 'code-smell',
37
61
  docsUrl: rule.docsUrl,
62
+ bestPracticeGuide: {
63
+ slug: docSlug,
64
+ uri: `mule-lint://docs/${docSlug}`,
65
+ hint: `Read the "${docSlug}" resource for detailed patterns, code examples, and checklists related to this rule.`,
66
+ },
38
67
  }, null, 2),
39
68
  },
40
69
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"getRuleDetails.js","sourceRoot":"","sources":["../../../../src/mcp/tools/getRuleDetails.ts"],"names":[],"mappings":";;AAQA,wDA4CC;AApDD,6BAAwB;AAGxB,uCAA0C;AAE1C;;GAEG;AACH,SAAgB,sBAAsB,CAAC,MAAiB;IACtD,iIAAiI;IAChI,MAAc,CAAC,IAAI,CAClB,kBAAkB,EAClB,mLAAmL,EACnL;QACE,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6DAA6D,CAAC;KAC3F,EACD,CAAC,EAAE,MAAM,EAAsB,EAAE,EAAE;QACjC,MAAM,IAAI,GAAG,IAAA,mBAAW,EAAC,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,mBAAmB,MAAM,EAAE;qBAClC;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;wBACE,EAAE,EAAE,IAAI,CAAC,EAAE;wBACX,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,WAAW,EAAE,IAAI,CAAC,WAAW;wBAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,YAAY;wBACzC,OAAO,EAAE,IAAI,CAAC,OAAO;qBACtB,EACD,IAAI,EACJ,CAAC,CACF;iBACF;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"getRuleDetails.js","sourceRoot":"","sources":["../../../../src/mcp/tools/getRuleDetails.ts"],"names":[],"mappings":";;AAgCA,wDAmDC;AAnFD,6BAAwB;AAGxB,uCAA0C;AAE1C;;;GAGG;AACH,MAAM,iBAAiB,GAA2B;IAChD,gBAAgB,EAAE,gBAAgB;IAClC,MAAM,EAAE,WAAW;IACnB,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE,aAAa;IAC1B,aAAa,EAAE,yBAAyB;IACxC,SAAS,EAAE,gBAAgB;IAC3B,UAAU,EAAE,aAAa;IACzB,SAAS,EAAE,kBAAkB;IAC7B,IAAI,EAAE,UAAU;IAChB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,gBAAgB;IAC3B,SAAS,EAAE,YAAY;IACvB,UAAU,EAAE,OAAO;IACnB,UAAU,EAAE,OAAO;IACnB,YAAY,EAAE,gBAAgB;CAC/B,CAAC;AAEF;;GAEG;AACH,SAAgB,sBAAsB,CAAC,MAAiB;IACtD,iIAAiI;IAChI,MAAc,CAAC,IAAI,CAClB,kBAAkB,EAClB,oQAAoQ,EACpQ;QACE,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6DAA6D,CAAC;KAC3F,EACD,CAAC,EAAE,MAAM,EAAsB,EAAE,EAAE;QACjC,MAAM,IAAI,GAAG,IAAA,mBAAW,EAAC,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,mBAAmB,MAAM,EAAE;qBAClC;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC;QAErE,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;wBACE,EAAE,EAAE,IAAI,CAAC,EAAE;wBACX,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,WAAW,EAAE,IAAI,CAAC,WAAW;wBAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,YAAY;wBACzC,OAAO,EAAE,IAAI,CAAC,OAAO;wBACrB,iBAAiB,EAAE;4BACjB,IAAI,EAAE,OAAO;4BACb,GAAG,EAAE,oBAAoB,OAAO,EAAE;4BAClC,IAAI,EAAE,aAAa,OAAO,uFAAuF;yBAClH;qBACF,EACD,IAAI,EACJ,CAAC,CACF;iBACF;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { ValidationContext, Issue, IssueType } from '../../types';
2
+ import { BaseRule } from '../base/BaseRule';
3
+ /**
4
+ * API-008: APIKit Console in Production
5
+ *
6
+ * The APIKit console endpoint should not be enabled in production.
7
+ * While useful for development, it exposes API documentation and
8
+ * testing capabilities that should be disabled in production
9
+ * environments.
10
+ *
11
+ * Detects: <apikit:console config-ref="..."/> elements
12
+ */
13
+ export declare class ApikitConsoleProductionRule extends BaseRule {
14
+ id: string;
15
+ name: string;
16
+ description: string;
17
+ severity: "warning";
18
+ category: "api-led";
19
+ issueType: IssueType;
20
+ validate(doc: Document, _context: ValidationContext): Issue[];
21
+ }
22
+ //# sourceMappingURL=ApikitConsoleProductionRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApikitConsoleProductionRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/api-led/ApikitConsoleProductionRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;GASG;AACH,qBAAa,2BAA4B,SAAQ,QAAQ;IACvD,EAAE,SAAa;IACf,IAAI,SAAkC;IACtC,WAAW,SAA8E;IACzF,QAAQ,EAAG,SAAS,CAAU;IAC9B,QAAQ,EAAG,SAAS,CAAU;IAC9B,SAAS,EAAE,SAAS,CAAmB;IAEvC,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;CAgC9D"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ApikitConsoleProductionRule = void 0;
4
+ const BaseRule_1 = require("../base/BaseRule");
5
+ /**
6
+ * API-008: APIKit Console in Production
7
+ *
8
+ * The APIKit console endpoint should not be enabled in production.
9
+ * While useful for development, it exposes API documentation and
10
+ * testing capabilities that should be disabled in production
11
+ * environments.
12
+ *
13
+ * Detects: <apikit:console config-ref="..."/> elements
14
+ */
15
+ class ApikitConsoleProductionRule extends BaseRule_1.BaseRule {
16
+ id = 'API-008';
17
+ name = 'APIKit Console in Production';
18
+ description = 'APIKit console should be disabled or protected in production deployments';
19
+ severity = 'warning';
20
+ category = 'api-led';
21
+ issueType = 'vulnerability';
22
+ validate(doc, _context) {
23
+ const issues = [];
24
+ // Find apikit:console elements
25
+ const consoleElements = this.select('//*[local-name()="console"]', doc);
26
+ for (const el of consoleElements) {
27
+ // Confirm it's an APIKit console (has config-ref or is in apikit namespace)
28
+ const configRef = this.getAttribute(el, 'config-ref');
29
+ const nodeName = el.nodeName ?? '';
30
+ // Only flag if it looks like an apikit console
31
+ if (nodeName.includes('apikit') ||
32
+ configRef?.includes('api') ||
33
+ configRef?.includes('router')) {
34
+ issues.push(this.createIssue(el, 'APIKit console is enabled — ensure it is disabled or protected in production', {
35
+ suggestion: 'Remove the apikit:console flow or gate it behind an environment check (e.g., only enable when mule.env != "prod")',
36
+ }));
37
+ }
38
+ }
39
+ return issues;
40
+ }
41
+ }
42
+ exports.ApikitConsoleProductionRule = ApikitConsoleProductionRule;
43
+ //# sourceMappingURL=ApikitConsoleProductionRule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApikitConsoleProductionRule.js","sourceRoot":"","sources":["../../../../src/rules/api-led/ApikitConsoleProductionRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;;GASG;AACH,MAAa,2BAA4B,SAAQ,mBAAQ;IACvD,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,8BAA8B,CAAC;IACtC,WAAW,GAAG,0EAA0E,CAAC;IACzF,QAAQ,GAAG,SAAkB,CAAC;IAC9B,QAAQ,GAAG,SAAkB,CAAC;IAC9B,SAAS,GAAc,eAAe,CAAC;IAEvC,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,+BAA+B;QAC/B,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;QAExE,KAAK,MAAM,EAAE,IAAI,eAAe,EAAE,CAAC;YACjC,4EAA4E;YAC5E,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;YACtD,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC;YAEnC,+CAA+C;YAC/C,IACE,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAC3B,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC;gBAC1B,SAAS,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAC7B,CAAC;gBACD,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,EAAE,EACF,8EAA8E,EAC9E;oBACE,UAAU,EACR,mHAAmH;iBACtH,CACF,CACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAxCD,kEAwCC"}
@@ -0,0 +1,24 @@
1
+ import { ValidationContext, Issue, IssueType } from '../../types';
2
+ import { BaseRule } from '../base/BaseRule';
3
+ /**
4
+ * API-006: APIKit Main Flow Structure
5
+ *
6
+ * The main flow in an APIKit project should follow the standard pattern:
7
+ * <http:listener> → <apikit:router>
8
+ *
9
+ * The main flow should not contain business logic — it should only
10
+ * receive requests and delegate to APIKit-generated implementation flows.
11
+ * This is the pattern used in all accelerator projects.
12
+ */
13
+ export declare class ApikitMainFlowStructureRule extends BaseRule {
14
+ id: string;
15
+ name: string;
16
+ description: string;
17
+ severity: "warning";
18
+ category: "api-led";
19
+ issueType: IssueType;
20
+ /** Max number of direct child elements (excluding error-handler) allowed in main flow */
21
+ private readonly MAX_MAIN_FLOW_CHILDREN;
22
+ validate(doc: Document, _context: ValidationContext): Issue[];
23
+ }
24
+ //# sourceMappingURL=ApikitMainFlowStructureRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApikitMainFlowStructureRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/api-led/ApikitMainFlowStructureRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;GASG;AACH,qBAAa,2BAA4B,SAAQ,QAAQ;IACvD,EAAE,SAAa;IACf,IAAI,SAAgC;IACpC,WAAW,SAAiF;IAC5F,QAAQ,EAAG,SAAS,CAAU;IAC9B,QAAQ,EAAG,SAAS,CAAU;IAC9B,SAAS,EAAE,SAAS,CAAgB;IAEpC,yFAAyF;IACzF,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAK;IAE5C,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;CA+C9D"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ApikitMainFlowStructureRule = void 0;
4
+ const BaseRule_1 = require("../base/BaseRule");
5
+ /**
6
+ * API-006: APIKit Main Flow Structure
7
+ *
8
+ * The main flow in an APIKit project should follow the standard pattern:
9
+ * <http:listener> → <apikit:router>
10
+ *
11
+ * The main flow should not contain business logic — it should only
12
+ * receive requests and delegate to APIKit-generated implementation flows.
13
+ * This is the pattern used in all accelerator projects.
14
+ */
15
+ class ApikitMainFlowStructureRule extends BaseRule_1.BaseRule {
16
+ id = 'API-006';
17
+ name = 'APIKit Main Flow Structure';
18
+ description = 'APIKit main flow should contain only listener and router, no business logic';
19
+ severity = 'warning';
20
+ category = 'api-led';
21
+ issueType = 'code-smell';
22
+ /** Max number of direct child elements (excluding error-handler) allowed in main flow */
23
+ MAX_MAIN_FLOW_CHILDREN = 4;
24
+ validate(doc, _context) {
25
+ const issues = [];
26
+ // Find flows that look like APIKit main flows
27
+ const flows = this.select('//mule:flow', doc);
28
+ for (const flow of flows) {
29
+ const flowName = this.getAttribute(flow, 'name') ?? '';
30
+ // Detect main flow: typically *-main or contains apikit:router
31
+ const hasRouter = this.exists('.//*[local-name()="router"]', flow);
32
+ if (!hasRouter) {
33
+ continue; // Not an APIKit main flow
34
+ }
35
+ const isMainFlow = flowName.endsWith('-main') ||
36
+ flowName.includes('-api-main') ||
37
+ flowName.includes('api-main');
38
+ if (!isMainFlow && !hasRouter) {
39
+ continue;
40
+ }
41
+ // Count child elements (excluding error-handler and comments)
42
+ const children = this.select('./*[not(local-name()="error-handler") and not(local-name()="description")]', flow);
43
+ if (children.length > this.MAX_MAIN_FLOW_CHILDREN) {
44
+ issues.push(this.createIssue(flow, `APIKit main flow "${flowName}" has ${children.length} operations — should contain only listener and router`, {
45
+ suggestion: 'Move business logic to APIKit implementation flows (e.g., get:\\resource:config). The main flow should only receive and route.',
46
+ }));
47
+ }
48
+ }
49
+ return issues;
50
+ }
51
+ }
52
+ exports.ApikitMainFlowStructureRule = ApikitMainFlowStructureRule;
53
+ //# sourceMappingURL=ApikitMainFlowStructureRule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApikitMainFlowStructureRule.js","sourceRoot":"","sources":["../../../../src/rules/api-led/ApikitMainFlowStructureRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;;GASG;AACH,MAAa,2BAA4B,SAAQ,mBAAQ;IACvD,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,4BAA4B,CAAC;IACpC,WAAW,GAAG,6EAA6E,CAAC;IAC5F,QAAQ,GAAG,SAAkB,CAAC;IAC9B,QAAQ,GAAG,SAAkB,CAAC;IAC9B,SAAS,GAAc,YAAY,CAAC;IAEpC,yFAAyF;IACxE,sBAAsB,GAAG,CAAC,CAAC;IAE5C,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,8CAA8C;QAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QAE9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;YAEvD,+DAA+D;YAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,6BAA6B,EAAE,IAAI,CAAC,CAAC;YAEnE,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,SAAS,CAAC,0BAA0B;YACtC,CAAC;YAED,MAAM,UAAU,GACd,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAC1B,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAC9B,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAEhC,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS,EAAE,CAAC;gBAC9B,SAAS;YACX,CAAC;YAED,8DAA8D;YAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAC1B,4EAA4E,EAC5E,IAAgB,CACjB,CAAC;YAEF,IAAI,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;gBAClD,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,IAAI,EACJ,qBAAqB,QAAQ,SAAS,QAAQ,CAAC,MAAM,uDAAuD,EAC5G;oBACE,UAAU,EACR,gIAAgI;iBACnI,CACF,CACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AA1DD,kEA0DC"}
@@ -0,0 +1,25 @@
1
+ import { ValidationContext, Issue, IssueType } from '../../types';
2
+ import { BaseRule } from '../base/BaseRule';
3
+ /**
4
+ * API-007: APIKit httpStatus Variable
5
+ *
6
+ * APIKit implementation flows should set the httpStatus variable so the
7
+ * HTTP listener can return the correct status code. The accelerator
8
+ * pattern uses ee:set-variable with variableName="httpStatus" in both
9
+ * success paths and error handlers.
10
+ *
11
+ * Common values: 200 (GET), 201 (POST/create), 204 (DELETE/no content)
12
+ */
13
+ export declare class ApikitStatusCodeVariableRule extends BaseRule {
14
+ id: string;
15
+ name: string;
16
+ description: string;
17
+ severity: "info";
18
+ category: "api-led";
19
+ issueType: IssueType;
20
+ /** Pattern that matches APIKit-generated flow names like get:\resource:config */
21
+ private readonly APIKIT_FLOW_PATTERN;
22
+ validate(doc: Document, _context: ValidationContext): Issue[];
23
+ private getExpectedStatusCode;
24
+ }
25
+ //# sourceMappingURL=ApikitStatusCodeVariableRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApikitStatusCodeVariableRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/api-led/ApikitStatusCodeVariableRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;GASG;AACH,qBAAa,4BAA6B,SAAQ,QAAQ;IACxD,EAAE,SAAa;IACf,IAAI,SAAiC;IACrC,WAAW,SAC+E;IAC1F,QAAQ,EAAG,MAAM,CAAU;IAC3B,QAAQ,EAAG,SAAS,CAAU;IAC9B,SAAS,EAAE,SAAS,CAAgB;IAEpC,iFAAiF;IACjF,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAkD;IAEtF,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;IAkC7D,OAAO,CAAC,qBAAqB;CAU9B"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ApikitStatusCodeVariableRule = void 0;
4
+ const BaseRule_1 = require("../base/BaseRule");
5
+ /**
6
+ * API-007: APIKit httpStatus Variable
7
+ *
8
+ * APIKit implementation flows should set the httpStatus variable so the
9
+ * HTTP listener can return the correct status code. The accelerator
10
+ * pattern uses ee:set-variable with variableName="httpStatus" in both
11
+ * success paths and error handlers.
12
+ *
13
+ * Common values: 200 (GET), 201 (POST/create), 204 (DELETE/no content)
14
+ */
15
+ class ApikitStatusCodeVariableRule extends BaseRule_1.BaseRule {
16
+ id = 'API-007';
17
+ name = 'APIKit Status Code Variable';
18
+ description = 'APIKit implementation flows should set httpStatus variable for correct response codes';
19
+ severity = 'info';
20
+ category = 'api-led';
21
+ issueType = 'code-smell';
22
+ /** Pattern that matches APIKit-generated flow names like get:\resource:config */
23
+ APIKIT_FLOW_PATTERN = /^(get|post|put|patch|delete|head|options):\\/;
24
+ validate(doc, _context) {
25
+ const issues = [];
26
+ const flows = this.select('//mule:flow', doc);
27
+ for (const flow of flows) {
28
+ const flowName = this.getAttribute(flow, 'name') ?? '';
29
+ // Only check APIKit implementation flows
30
+ if (!this.APIKIT_FLOW_PATTERN.test(flowName)) {
31
+ continue;
32
+ }
33
+ // Check if httpStatus is set anywhere in the flow
34
+ const setsHttpStatus = this.exists('.//*[local-name()="set-variable" and @variableName="httpStatus"]', flow) ||
35
+ this.exists('.//*[local-name()="set-variable" and @variableName="httpStatus"]', flow);
36
+ if (!setsHttpStatus) {
37
+ // Determine expected status code from HTTP method
38
+ const method = flowName.split(':')[0].toUpperCase();
39
+ const expectedCode = this.getExpectedStatusCode(method);
40
+ issues.push(this.createIssue(flow, `APIKit flow "${flowName}" does not set httpStatus variable`, {
41
+ suggestion: `Add <set-variable variableName="httpStatus" value="${expectedCode}"/> for ${method} operations`,
42
+ }));
43
+ }
44
+ }
45
+ return issues;
46
+ }
47
+ getExpectedStatusCode(method) {
48
+ switch (method) {
49
+ case 'POST':
50
+ return '201';
51
+ case 'DELETE':
52
+ return '204';
53
+ default:
54
+ return '200';
55
+ }
56
+ }
57
+ }
58
+ exports.ApikitStatusCodeVariableRule = ApikitStatusCodeVariableRule;
59
+ //# sourceMappingURL=ApikitStatusCodeVariableRule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApikitStatusCodeVariableRule.js","sourceRoot":"","sources":["../../../../src/rules/api-led/ApikitStatusCodeVariableRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;;GASG;AACH,MAAa,4BAA6B,SAAQ,mBAAQ;IACxD,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,6BAA6B,CAAC;IACrC,WAAW,GACT,uFAAuF,CAAC;IAC1F,QAAQ,GAAG,MAAe,CAAC;IAC3B,QAAQ,GAAG,SAAkB,CAAC;IAC9B,SAAS,GAAc,YAAY,CAAC;IAEpC,iFAAiF;IAChE,mBAAmB,GAAG,8CAA8C,CAAC;IAEtF,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QAE9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;YAEvD,yCAAyC;YACzC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC7C,SAAS;YACX,CAAC;YAED,kDAAkD;YAClD,MAAM,cAAc,GAClB,IAAI,CAAC,MAAM,CAAC,kEAAkE,EAAE,IAAI,CAAC;gBACrF,IAAI,CAAC,MAAM,CAAC,kEAAkE,EAAE,IAAI,CAAC,CAAC;YAExF,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,kDAAkD;gBAClD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;gBACpD,MAAM,YAAY,GAAG,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;gBAExD,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,gBAAgB,QAAQ,oCAAoC,EAAE;oBACnF,UAAU,EAAE,sDAAsD,YAAY,WAAW,MAAM,aAAa;iBAC7G,CAAC,CACH,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,qBAAqB,CAAC,MAAc;QAC1C,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,MAAM;gBACT,OAAO,KAAK,CAAC;YACf,KAAK,QAAQ;gBACX,OAAO,KAAK,CAAC;YACf;gBACE,OAAO,KAAK,CAAC;QACjB,CAAC;IACH,CAAC;CACF;AAxDD,oEAwDC"}
@@ -0,0 +1,24 @@
1
+ import { ValidationContext, Issue, IssueType } from '../../types';
2
+ import { BaseRule } from '../base/BaseRule';
3
+ /**
4
+ * SF-002: Event Listener Null Guard
5
+ *
6
+ * Salesforce CDC (Change Data Capture) and Platform Event listeners receive
7
+ * events where fields can be null (e.g., unchanged fields in CDC events
8
+ * come through as null). Flows processing these events should include
9
+ * null-safety checks to avoid NullPointerExceptions.
10
+ *
11
+ * This rule flags flows with Salesforce event listeners (subscribe-channel,
12
+ * replay-channel) that contain DataWeave transforms accessing payload fields
13
+ * without null-safety operators (?., default, !isEmpty, etc.).
14
+ */
15
+ export declare class EventListenerNullGuardRule extends BaseRule {
16
+ id: string;
17
+ name: string;
18
+ description: string;
19
+ severity: "info";
20
+ category: "operations";
21
+ issueType: IssueType;
22
+ validate(doc: Document, _context: ValidationContext): Issue[];
23
+ }
24
+ //# sourceMappingURL=EventListenerNullGuardRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventListenerNullGuardRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/connector/EventListenerNullGuardRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;;;GAWG;AACH,qBAAa,0BAA2B,SAAQ,QAAQ;IACtD,EAAE,SAAY;IACd,IAAI,SAA+B;IACnC,WAAW,SAC4F;IACvG,QAAQ,EAAG,MAAM,CAAU;IAC3B,QAAQ,EAAG,YAAY,CAAU;IACjC,SAAS,EAAE,SAAS,CAAS;IAE7B,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;CAoD9D"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventListenerNullGuardRule = void 0;
4
+ const BaseRule_1 = require("../base/BaseRule");
5
+ /**
6
+ * SF-002: Event Listener Null Guard
7
+ *
8
+ * Salesforce CDC (Change Data Capture) and Platform Event listeners receive
9
+ * events where fields can be null (e.g., unchanged fields in CDC events
10
+ * come through as null). Flows processing these events should include
11
+ * null-safety checks to avoid NullPointerExceptions.
12
+ *
13
+ * This rule flags flows with Salesforce event listeners (subscribe-channel,
14
+ * replay-channel) that contain DataWeave transforms accessing payload fields
15
+ * without null-safety operators (?., default, !isEmpty, etc.).
16
+ */
17
+ class EventListenerNullGuardRule extends BaseRule_1.BaseRule {
18
+ id = 'SF-002';
19
+ name = 'Event Listener Null Guard';
20
+ description = 'Salesforce CDC/Platform Event listeners should include null-safety checks for event payload fields';
21
+ severity = 'info';
22
+ category = 'operations';
23
+ issueType = 'bug';
24
+ validate(doc, _context) {
25
+ const issues = [];
26
+ const flows = this.select('//mule:flow', doc);
27
+ for (const flow of flows) {
28
+ const flowName = this.getAttribute(flow, 'name') ?? '';
29
+ // Check if this flow has a Salesforce event source (CDC or Platform Event)
30
+ const hasSfListener = this.exists('.//*[local-name()="subscribe-channel" or local-name()="replay-channel" or local-name()="subscribe-topic" or local-name()="replay-topic"]', flow);
31
+ if (!hasSfListener) {
32
+ continue;
33
+ }
34
+ // Find DataWeave transforms in this flow
35
+ const transforms = this.select('.//*[local-name()="transform"]', flow);
36
+ for (const transform of transforms) {
37
+ const transformText = transform.textContent ?? '';
38
+ // Check if the transform accesses payload fields directly without null guards
39
+ // Look for patterns like: payload.fieldName (without ?.)
40
+ const hasDirectAccess = /payload\.\w+/.test(transformText);
41
+ const hasNullSafety = /payload\?\.\w+/.test(transformText) ||
42
+ /default\s/.test(transformText) ||
43
+ /isEmpty/.test(transformText) ||
44
+ /if\s*\(/.test(transformText) ||
45
+ /unless/.test(transformText) ||
46
+ /payload\s+default/.test(transformText);
47
+ if (hasDirectAccess && !hasNullSafety) {
48
+ issues.push(this.createIssue(transform, `DataWeave transform in CDC/event flow "${flowName}" accesses payload fields without null-safety checks`, {
49
+ suggestion: 'Use null-safe navigation (payload?.field), default operators, or isEmpty checks when processing CDC event payloads — unchanged fields arrive as null',
50
+ }));
51
+ }
52
+ }
53
+ }
54
+ return issues;
55
+ }
56
+ }
57
+ exports.EventListenerNullGuardRule = EventListenerNullGuardRule;
58
+ //# sourceMappingURL=EventListenerNullGuardRule.js.map