@memberjunction/react-linter 0.0.1 → 5.38.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 (330) hide show
  1. package/dist/component-linter.d.ts +77 -0
  2. package/dist/component-linter.d.ts.map +1 -0
  3. package/dist/component-linter.js +1206 -0
  4. package/dist/component-linter.js.map +1 -0
  5. package/dist/control-flow-analyzer.d.ts +184 -0
  6. package/dist/control-flow-analyzer.d.ts.map +1 -0
  7. package/dist/control-flow-analyzer.js +798 -0
  8. package/dist/control-flow-analyzer.js.map +1 -0
  9. package/dist/index.d.ts +6 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +8 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/library-lint-cache.d.ts +50 -0
  14. package/dist/library-lint-cache.d.ts.map +1 -0
  15. package/dist/library-lint-cache.js +173 -0
  16. package/dist/library-lint-cache.js.map +1 -0
  17. package/dist/lint-rule.d.ts +70 -0
  18. package/dist/lint-rule.d.ts.map +1 -0
  19. package/dist/lint-rule.js +30 -0
  20. package/dist/lint-rule.js.map +1 -0
  21. package/dist/lint-utils.d.ts +131 -0
  22. package/dist/lint-utils.d.ts.map +1 -0
  23. package/dist/lint-utils.js +358 -0
  24. package/dist/lint-utils.js.map +1 -0
  25. package/dist/linter-options.d.ts +51 -0
  26. package/dist/linter-options.d.ts.map +1 -0
  27. package/dist/linter-options.js +2 -0
  28. package/dist/linter-options.js.map +1 -0
  29. package/dist/prop-value-extractor.d.ts +147 -0
  30. package/dist/prop-value-extractor.d.ts.map +1 -0
  31. package/dist/prop-value-extractor.js +472 -0
  32. package/dist/prop-value-extractor.js.map +1 -0
  33. package/dist/runtime-rules/ai-tools-availability-check.d.ts +9 -0
  34. package/dist/runtime-rules/ai-tools-availability-check.d.ts.map +1 -0
  35. package/dist/runtime-rules/ai-tools-availability-check.js +223 -0
  36. package/dist/runtime-rules/ai-tools-availability-check.js.map +1 -0
  37. package/dist/runtime-rules/callback-event-validation.d.ts +22 -0
  38. package/dist/runtime-rules/callback-event-validation.d.ts.map +1 -0
  39. package/dist/runtime-rules/callback-event-validation.js +561 -0
  40. package/dist/runtime-rules/callback-event-validation.js.map +1 -0
  41. package/dist/runtime-rules/chart-field-validation.d.ts +10 -0
  42. package/dist/runtime-rules/chart-field-validation.d.ts.map +1 -0
  43. package/dist/runtime-rules/chart-field-validation.js +270 -0
  44. package/dist/runtime-rules/chart-field-validation.js.map +1 -0
  45. package/dist/runtime-rules/child-component-prop-validation.d.ts +11 -0
  46. package/dist/runtime-rules/child-component-prop-validation.d.ts.map +1 -0
  47. package/dist/runtime-rules/child-component-prop-validation.js +443 -0
  48. package/dist/runtime-rules/child-component-prop-validation.js.map +1 -0
  49. package/dist/runtime-rules/component-name-mismatch.d.ts +19 -0
  50. package/dist/runtime-rules/component-name-mismatch.d.ts.map +1 -0
  51. package/dist/runtime-rules/component-name-mismatch.js +82 -0
  52. package/dist/runtime-rules/component-name-mismatch.js.map +1 -0
  53. package/dist/runtime-rules/component-not-in-dependencies.d.ts +20 -0
  54. package/dist/runtime-rules/component-not-in-dependencies.d.ts.map +1 -0
  55. package/dist/runtime-rules/component-not-in-dependencies.js +92 -0
  56. package/dist/runtime-rules/component-not-in-dependencies.js.map +1 -0
  57. package/dist/runtime-rules/component-props-validation.d.ts +25 -0
  58. package/dist/runtime-rules/component-props-validation.d.ts.map +1 -0
  59. package/dist/runtime-rules/component-props-validation.js +228 -0
  60. package/dist/runtime-rules/component-props-validation.js.map +1 -0
  61. package/dist/runtime-rules/component-usage-without-destructuring.d.ts +20 -0
  62. package/dist/runtime-rules/component-usage-without-destructuring.d.ts.map +1 -0
  63. package/dist/runtime-rules/component-usage-without-destructuring.js +124 -0
  64. package/dist/runtime-rules/component-usage-without-destructuring.js.map +1 -0
  65. package/dist/runtime-rules/data-result-validation.d.ts +9 -0
  66. package/dist/runtime-rules/data-result-validation.d.ts.map +1 -0
  67. package/dist/runtime-rules/data-result-validation.js +763 -0
  68. package/dist/runtime-rules/data-result-validation.js.map +1 -0
  69. package/dist/runtime-rules/datagrid-field-validation.d.ts +10 -0
  70. package/dist/runtime-rules/datagrid-field-validation.d.ts.map +1 -0
  71. package/dist/runtime-rules/datagrid-field-validation.js +249 -0
  72. package/dist/runtime-rules/datagrid-field-validation.js.map +1 -0
  73. package/dist/runtime-rules/dependency-shadowing.d.ts +20 -0
  74. package/dist/runtime-rules/dependency-shadowing.d.ts.map +1 -0
  75. package/dist/runtime-rules/dependency-shadowing.js +147 -0
  76. package/dist/runtime-rules/dependency-shadowing.js.map +1 -0
  77. package/dist/runtime-rules/entity-field-access-validation.d.ts +12 -0
  78. package/dist/runtime-rules/entity-field-access-validation.d.ts.map +1 -0
  79. package/dist/runtime-rules/entity-field-access-validation.js +304 -0
  80. package/dist/runtime-rules/entity-field-access-validation.js.map +1 -0
  81. package/dist/runtime-rules/event-parameter-validation.d.ts +22 -0
  82. package/dist/runtime-rules/event-parameter-validation.d.ts.map +1 -0
  83. package/dist/runtime-rules/event-parameter-validation.js +406 -0
  84. package/dist/runtime-rules/event-parameter-validation.js.map +1 -0
  85. package/dist/runtime-rules/index.d.ts +61 -0
  86. package/dist/runtime-rules/index.d.ts.map +1 -0
  87. package/dist/runtime-rules/index.js +62 -0
  88. package/dist/runtime-rules/index.js.map +1 -0
  89. package/dist/runtime-rules/library-variable-names.d.ts +24 -0
  90. package/dist/runtime-rules/library-variable-names.d.ts.map +1 -0
  91. package/dist/runtime-rules/library-variable-names.js +88 -0
  92. package/dist/runtime-rules/library-variable-names.js.map +1 -0
  93. package/dist/runtime-rules/no-child-implementation.d.ts +18 -0
  94. package/dist/runtime-rules/no-child-implementation.d.ts.map +1 -0
  95. package/dist/runtime-rules/no-child-implementation.js +57 -0
  96. package/dist/runtime-rules/no-child-implementation.js.map +1 -0
  97. package/dist/runtime-rules/no-data-prop.d.ts +22 -0
  98. package/dist/runtime-rules/no-data-prop.d.ts.map +1 -0
  99. package/dist/runtime-rules/no-data-prop.js +111 -0
  100. package/dist/runtime-rules/no-data-prop.js.map +1 -0
  101. package/dist/runtime-rules/no-export-statements.d.ts +18 -0
  102. package/dist/runtime-rules/no-export-statements.d.ts.map +1 -0
  103. package/dist/runtime-rules/no-export-statements.js +143 -0
  104. package/dist/runtime-rules/no-export-statements.js.map +1 -0
  105. package/dist/runtime-rules/no-iife-wrapper.d.ts +18 -0
  106. package/dist/runtime-rules/no-iife-wrapper.d.ts.map +1 -0
  107. package/dist/runtime-rules/no-iife-wrapper.js +217 -0
  108. package/dist/runtime-rules/no-iife-wrapper.js.map +1 -0
  109. package/dist/runtime-rules/no-import-statements.d.ts +18 -0
  110. package/dist/runtime-rules/no-import-statements.d.ts.map +1 -0
  111. package/dist/runtime-rules/no-import-statements.js +65 -0
  112. package/dist/runtime-rules/no-import-statements.js.map +1 -0
  113. package/dist/runtime-rules/no-react-destructuring.d.ts +18 -0
  114. package/dist/runtime-rules/no-react-destructuring.d.ts.map +1 -0
  115. package/dist/runtime-rules/no-react-destructuring.js +60 -0
  116. package/dist/runtime-rules/no-react-destructuring.js.map +1 -0
  117. package/dist/runtime-rules/no-require-statements.d.ts +18 -0
  118. package/dist/runtime-rules/no-require-statements.d.ts.map +1 -0
  119. package/dist/runtime-rules/no-require-statements.js +109 -0
  120. package/dist/runtime-rules/no-require-statements.js.map +1 -0
  121. package/dist/runtime-rules/no-return-component.d.ts +18 -0
  122. package/dist/runtime-rules/no-return-component.d.ts.map +1 -0
  123. package/dist/runtime-rules/no-return-component.js +106 -0
  124. package/dist/runtime-rules/no-return-component.js.map +1 -0
  125. package/dist/runtime-rules/no-unwrap-utility-libs.d.ts +20 -0
  126. package/dist/runtime-rules/no-unwrap-utility-libs.d.ts.map +1 -0
  127. package/dist/runtime-rules/no-unwrap-utility-libs.js +75 -0
  128. package/dist/runtime-rules/no-unwrap-utility-libs.js.map +1 -0
  129. package/dist/runtime-rules/no-use-reducer.d.ts +19 -0
  130. package/dist/runtime-rules/no-use-reducer.d.ts.map +1 -0
  131. package/dist/runtime-rules/no-use-reducer.js +78 -0
  132. package/dist/runtime-rules/no-use-reducer.js.map +1 -0
  133. package/dist/runtime-rules/no-window-access.d.ts +23 -0
  134. package/dist/runtime-rules/no-window-access.d.ts.map +1 -0
  135. package/dist/runtime-rules/no-window-access.js +136 -0
  136. package/dist/runtime-rules/no-window-access.js.map +1 -0
  137. package/dist/runtime-rules/noisy-settings-updates.d.ts +18 -0
  138. package/dist/runtime-rules/noisy-settings-updates.d.ts.map +1 -0
  139. package/dist/runtime-rules/noisy-settings-updates.js +110 -0
  140. package/dist/runtime-rules/noisy-settings-updates.js.map +1 -0
  141. package/dist/runtime-rules/overflow-hidden-on-layout-container.d.ts +30 -0
  142. package/dist/runtime-rules/overflow-hidden-on-layout-container.d.ts.map +1 -0
  143. package/dist/runtime-rules/overflow-hidden-on-layout-container.js +220 -0
  144. package/dist/runtime-rules/overflow-hidden-on-layout-container.js.map +1 -0
  145. package/dist/runtime-rules/pass-standard-props.d.ts +19 -0
  146. package/dist/runtime-rules/pass-standard-props.d.ts.map +1 -0
  147. package/dist/runtime-rules/pass-standard-props.js +82 -0
  148. package/dist/runtime-rules/pass-standard-props.js.map +1 -0
  149. package/dist/runtime-rules/prefer-async-await.d.ts +17 -0
  150. package/dist/runtime-rules/prefer-async-await.d.ts.map +1 -0
  151. package/dist/runtime-rules/prefer-async-await.js +52 -0
  152. package/dist/runtime-rules/prefer-async-await.js.map +1 -0
  153. package/dist/runtime-rules/prefer-jsx-syntax.d.ts +17 -0
  154. package/dist/runtime-rules/prefer-jsx-syntax.d.ts.map +1 -0
  155. package/dist/runtime-rules/prefer-jsx-syntax.js +51 -0
  156. package/dist/runtime-rules/prefer-jsx-syntax.js.map +1 -0
  157. package/dist/runtime-rules/prop-state-sync.d.ts +19 -0
  158. package/dist/runtime-rules/prop-state-sync.d.ts.map +1 -0
  159. package/dist/runtime-rules/prop-state-sync.js +76 -0
  160. package/dist/runtime-rules/prop-state-sync.js.map +1 -0
  161. package/dist/runtime-rules/property-name-consistency.d.ts +20 -0
  162. package/dist/runtime-rules/property-name-consistency.d.ts.map +1 -0
  163. package/dist/runtime-rules/property-name-consistency.js +172 -0
  164. package/dist/runtime-rules/property-name-consistency.js.map +1 -0
  165. package/dist/runtime-rules/query-result-field-access-validation.d.ts +10 -0
  166. package/dist/runtime-rules/query-result-field-access-validation.d.ts.map +1 -0
  167. package/dist/runtime-rules/query-result-field-access-validation.js +304 -0
  168. package/dist/runtime-rules/query-result-field-access-validation.js.map +1 -0
  169. package/dist/runtime-rules/react-component-naming.d.ts +19 -0
  170. package/dist/runtime-rules/react-component-naming.d.ts.map +1 -0
  171. package/dist/runtime-rules/react-component-naming.js +72 -0
  172. package/dist/runtime-rules/react-component-naming.js.map +1 -0
  173. package/dist/runtime-rules/react-hooks-rules.d.ts +27 -0
  174. package/dist/runtime-rules/react-hooks-rules.d.ts.map +1 -0
  175. package/dist/runtime-rules/react-hooks-rules.js +223 -0
  176. package/dist/runtime-rules/react-hooks-rules.js.map +1 -0
  177. package/dist/runtime-rules/required-queries-not-called.d.ts +19 -0
  178. package/dist/runtime-rules/required-queries-not-called.d.ts.map +1 -0
  179. package/dist/runtime-rules/required-queries-not-called.js +146 -0
  180. package/dist/runtime-rules/required-queries-not-called.js.map +1 -0
  181. package/dist/runtime-rules/runquery-call-validation.d.ts +11 -0
  182. package/dist/runtime-rules/runquery-call-validation.d.ts.map +1 -0
  183. package/dist/runtime-rules/runquery-call-validation.js +886 -0
  184. package/dist/runtime-rules/runquery-call-validation.js.map +1 -0
  185. package/dist/runtime-rules/runview-call-validation.d.ts +10 -0
  186. package/dist/runtime-rules/runview-call-validation.d.ts.map +1 -0
  187. package/dist/runtime-rules/runview-call-validation.js +336 -0
  188. package/dist/runtime-rules/runview-call-validation.js.map +1 -0
  189. package/dist/runtime-rules/saved-user-settings-pattern.d.ts +19 -0
  190. package/dist/runtime-rules/saved-user-settings-pattern.d.ts.map +1 -0
  191. package/dist/runtime-rules/saved-user-settings-pattern.js +90 -0
  192. package/dist/runtime-rules/saved-user-settings-pattern.js.map +1 -0
  193. package/dist/runtime-rules/search-availability-check.d.ts +9 -0
  194. package/dist/runtime-rules/search-availability-check.d.ts.map +1 -0
  195. package/dist/runtime-rules/search-availability-check.js +220 -0
  196. package/dist/runtime-rules/search-availability-check.js.map +1 -0
  197. package/dist/runtime-rules/search-call-validation.d.ts +9 -0
  198. package/dist/runtime-rules/search-call-validation.d.ts.map +1 -0
  199. package/dist/runtime-rules/search-call-validation.js +336 -0
  200. package/dist/runtime-rules/search-call-validation.js.map +1 -0
  201. package/dist/runtime-rules/server-reload-on-client-operation.d.ts +18 -0
  202. package/dist/runtime-rules/server-reload-on-client-operation.d.ts.map +1 -0
  203. package/dist/runtime-rules/server-reload-on-client-operation.js +107 -0
  204. package/dist/runtime-rules/server-reload-on-client-operation.js.map +1 -0
  205. package/dist/runtime-rules/single-function-only.d.ts +18 -0
  206. package/dist/runtime-rules/single-function-only.d.ts.map +1 -0
  207. package/dist/runtime-rules/single-function-only.js +103 -0
  208. package/dist/runtime-rules/single-function-only.js.map +1 -0
  209. package/dist/runtime-rules/string-replace-all-occurrences.d.ts +19 -0
  210. package/dist/runtime-rules/string-replace-all-occurrences.d.ts.map +1 -0
  211. package/dist/runtime-rules/string-replace-all-occurrences.js +109 -0
  212. package/dist/runtime-rules/string-replace-all-occurrences.js.map +1 -0
  213. package/dist/runtime-rules/string-template-validation.d.ts +22 -0
  214. package/dist/runtime-rules/string-template-validation.d.ts.map +1 -0
  215. package/dist/runtime-rules/string-template-validation.js +163 -0
  216. package/dist/runtime-rules/string-template-validation.js.map +1 -0
  217. package/dist/runtime-rules/styles-validation.d.ts +10 -0
  218. package/dist/runtime-rules/styles-validation.d.ts.map +1 -0
  219. package/dist/runtime-rules/styles-validation.js +153 -0
  220. package/dist/runtime-rules/styles-validation.js.map +1 -0
  221. package/dist/runtime-rules/type-inference-errors.d.ts +23 -0
  222. package/dist/runtime-rules/type-inference-errors.d.ts.map +1 -0
  223. package/dist/runtime-rules/type-inference-errors.js +53 -0
  224. package/dist/runtime-rules/type-inference-errors.js.map +1 -0
  225. package/dist/runtime-rules/type-mismatch-operation.d.ts +23 -0
  226. package/dist/runtime-rules/type-mismatch-operation.d.ts.map +1 -0
  227. package/dist/runtime-rules/type-mismatch-operation.js +145 -0
  228. package/dist/runtime-rules/type-mismatch-operation.js.map +1 -0
  229. package/dist/runtime-rules/undefined-component-usage.d.ts +20 -0
  230. package/dist/runtime-rules/undefined-component-usage.d.ts.map +1 -0
  231. package/dist/runtime-rules/undefined-component-usage.js +138 -0
  232. package/dist/runtime-rules/undefined-component-usage.js.map +1 -0
  233. package/dist/runtime-rules/undefined-jsx-component.d.ts +25 -0
  234. package/dist/runtime-rules/undefined-jsx-component.d.ts.map +1 -0
  235. package/dist/runtime-rules/undefined-jsx-component.js +269 -0
  236. package/dist/runtime-rules/undefined-jsx-component.js.map +1 -0
  237. package/dist/runtime-rules/unsafe-array-operations.d.ts +25 -0
  238. package/dist/runtime-rules/unsafe-array-operations.d.ts.map +1 -0
  239. package/dist/runtime-rules/unsafe-array-operations.js +347 -0
  240. package/dist/runtime-rules/unsafe-array-operations.js.map +1 -0
  241. package/dist/runtime-rules/unsafe-formatting-methods.d.ts +24 -0
  242. package/dist/runtime-rules/unsafe-formatting-methods.d.ts.map +1 -0
  243. package/dist/runtime-rules/unsafe-formatting-methods.js +277 -0
  244. package/dist/runtime-rules/unsafe-formatting-methods.js.map +1 -0
  245. package/dist/runtime-rules/unused-component-dependencies.d.ts +19 -0
  246. package/dist/runtime-rules/unused-component-dependencies.d.ts.map +1 -0
  247. package/dist/runtime-rules/unused-component-dependencies.js +90 -0
  248. package/dist/runtime-rules/unused-component-dependencies.js.map +1 -0
  249. package/dist/runtime-rules/unused-libraries.d.ts +19 -0
  250. package/dist/runtime-rules/unused-libraries.d.ts.map +1 -0
  251. package/dist/runtime-rules/unused-libraries.js +127 -0
  252. package/dist/runtime-rules/unused-libraries.js.map +1 -0
  253. package/dist/runtime-rules/use-function-declaration.d.ts +18 -0
  254. package/dist/runtime-rules/use-function-declaration.d.ts.map +1 -0
  255. package/dist/runtime-rules/use-function-declaration.js +127 -0
  256. package/dist/runtime-rules/use-function-declaration.js.map +1 -0
  257. package/dist/runtime-rules/use-unwrap-components.d.ts +19 -0
  258. package/dist/runtime-rules/use-unwrap-components.d.ts.map +1 -0
  259. package/dist/runtime-rules/use-unwrap-components.js +84 -0
  260. package/dist/runtime-rules/use-unwrap-components.js.map +1 -0
  261. package/dist/runtime-rules/useeffect-unstable-dependencies.d.ts +23 -0
  262. package/dist/runtime-rules/useeffect-unstable-dependencies.d.ts.map +1 -0
  263. package/dist/runtime-rules/useeffect-unstable-dependencies.js +215 -0
  264. package/dist/runtime-rules/useeffect-unstable-dependencies.js.map +1 -0
  265. package/dist/runtime-rules/utilities-api-validation.d.ts +24 -0
  266. package/dist/runtime-rules/utilities-api-validation.d.ts.map +1 -0
  267. package/dist/runtime-rules/utilities-api-validation.js +121 -0
  268. package/dist/runtime-rules/utilities-api-validation.js.map +1 -0
  269. package/dist/runtime-rules/utilities-no-direct-instantiation.d.ts +20 -0
  270. package/dist/runtime-rules/utilities-no-direct-instantiation.d.ts.map +1 -0
  271. package/dist/runtime-rules/utilities-no-direct-instantiation.js +58 -0
  272. package/dist/runtime-rules/utilities-no-direct-instantiation.js.map +1 -0
  273. package/dist/runtime-rules/validate-component-references.d.ts +19 -0
  274. package/dist/runtime-rules/validate-component-references.d.ts.map +1 -0
  275. package/dist/runtime-rules/validate-component-references.js +255 -0
  276. package/dist/runtime-rules/validate-component-references.js.map +1 -0
  277. package/dist/schema-validation/component-prop-rule.d.ts +131 -0
  278. package/dist/schema-validation/component-prop-rule.d.ts.map +1 -0
  279. package/dist/schema-validation/component-prop-rule.js +625 -0
  280. package/dist/schema-validation/component-prop-rule.js.map +1 -0
  281. package/dist/schema-validation/index.d.ts +26 -0
  282. package/dist/schema-validation/index.d.ts.map +1 -0
  283. package/dist/schema-validation/index.js +26 -0
  284. package/dist/schema-validation/index.js.map +1 -0
  285. package/dist/schema-validation/semantic-validators/index.d.ts +23 -0
  286. package/dist/schema-validation/semantic-validators/index.d.ts.map +1 -0
  287. package/dist/schema-validation/semantic-validators/index.js +23 -0
  288. package/dist/schema-validation/semantic-validators/index.js.map +1 -0
  289. package/dist/schema-validation/semantic-validators/required-when-validator.d.ts +43 -0
  290. package/dist/schema-validation/semantic-validators/required-when-validator.d.ts.map +1 -0
  291. package/dist/schema-validation/semantic-validators/required-when-validator.js +94 -0
  292. package/dist/schema-validation/semantic-validators/required-when-validator.js.map +1 -0
  293. package/dist/schema-validation/semantic-validators/semantic-validator-registry.d.ts +122 -0
  294. package/dist/schema-validation/semantic-validators/semantic-validator-registry.d.ts.map +1 -0
  295. package/dist/schema-validation/semantic-validators/semantic-validator-registry.js +166 -0
  296. package/dist/schema-validation/semantic-validators/semantic-validator-registry.js.map +1 -0
  297. package/dist/schema-validation/semantic-validators/semantic-validator.d.ts +260 -0
  298. package/dist/schema-validation/semantic-validators/semantic-validator.d.ts.map +1 -0
  299. package/dist/schema-validation/semantic-validators/semantic-validator.js +301 -0
  300. package/dist/schema-validation/semantic-validators/semantic-validator.js.map +1 -0
  301. package/dist/schema-validation/semantic-validators/sql-where-clause-validator.d.ts +115 -0
  302. package/dist/schema-validation/semantic-validators/sql-where-clause-validator.d.ts.map +1 -0
  303. package/dist/schema-validation/semantic-validators/sql-where-clause-validator.js +381 -0
  304. package/dist/schema-validation/semantic-validators/sql-where-clause-validator.js.map +1 -0
  305. package/dist/schema-validation/semantic-validators/subset-of-entity-fields-validator.d.ts +60 -0
  306. package/dist/schema-validation/semantic-validators/subset-of-entity-fields-validator.d.ts.map +1 -0
  307. package/dist/schema-validation/semantic-validators/subset-of-entity-fields-validator.js +195 -0
  308. package/dist/schema-validation/semantic-validators/subset-of-entity-fields-validator.js.map +1 -0
  309. package/dist/schema-validation/semantic-validators/validation-context.d.ts +335 -0
  310. package/dist/schema-validation/semantic-validators/validation-context.d.ts.map +1 -0
  311. package/dist/schema-validation/semantic-validators/validation-context.js +13 -0
  312. package/dist/schema-validation/semantic-validators/validation-context.js.map +1 -0
  313. package/dist/styles-type-analyzer.d.ts +64 -0
  314. package/dist/styles-type-analyzer.d.ts.map +1 -0
  315. package/dist/styles-type-analyzer.js +242 -0
  316. package/dist/styles-type-analyzer.js.map +1 -0
  317. package/dist/type-context.d.ts +184 -0
  318. package/dist/type-context.d.ts.map +1 -0
  319. package/dist/type-context.js +415 -0
  320. package/dist/type-context.js.map +1 -0
  321. package/dist/type-inference-engine.d.ts +181 -0
  322. package/dist/type-inference-engine.d.ts.map +1 -0
  323. package/dist/type-inference-engine.js +1151 -0
  324. package/dist/type-inference-engine.js.map +1 -0
  325. package/dist/type-rules/type-compatibility-rule.d.ts +85 -0
  326. package/dist/type-rules/type-compatibility-rule.d.ts.map +1 -0
  327. package/dist/type-rules/type-compatibility-rule.js +211 -0
  328. package/dist/type-rules/type-compatibility-rule.js.map +1 -0
  329. package/package.json +35 -7
  330. package/README.md +0 -45
@@ -0,0 +1,886 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { traverse, isStringLike, isNumberLike, isObjectLike } from '../lint-utils.js';
8
+ import { RegisterClass } from '@memberjunction/global';
9
+ import * as t from '@babel/types';
10
+ import { BaseLintRule } from '../lint-rule.js';
11
+ import { mapSQLTypeToJSType } from '../type-context.js';
12
+ /**
13
+ * Rule: runquery-call-validation
14
+ *
15
+ * Consolidates all RunQuery CALL SITE validation into a single traversal.
16
+ * Absorbs checks from:
17
+ * - runview-runquery-valid-properties (RunQuery portion)
18
+ * - runquery-parameters-validation (all)
19
+ * - query-parameter-type-validation (all)
20
+ * - query-param-null-check (all)
21
+ * - runquery-missing-categorypath (all)
22
+ * - runquery-runview-validation (all)
23
+ *
24
+ * Severity: critical/high/medium
25
+ * Applies to: all components
26
+ */
27
+ const RULE_NAME = 'runquery-call-validation';
28
+ /** Valid properties for RunQuery */
29
+ const VALID_RUNQUERY_PROPS = new Set([
30
+ 'QueryID', 'QueryName', 'CategoryID', 'CategoryPath',
31
+ 'Parameters', 'MaxRows', 'StartRow', 'ForceAuditLog', 'AuditLogDescription',
32
+ ]);
33
+ /** SQL keywords for injection detection */
34
+ /**
35
+ * SQL structural patterns that indicate actual SQL statements, not query names.
36
+ * Requires multiple keywords in combination to avoid false positives on
37
+ * domain terms like "Join Year", "Update Status", "Revenue From Events".
38
+ */
39
+ const SQL_PATTERNS = [
40
+ /\bSELECT\b.*\bFROM\b/i, // SELECT ... FROM
41
+ /\bINSERT\b.*\bINTO\b/i, // INSERT INTO
42
+ /\bUPDATE\b.*\bSET\b/i, // UPDATE ... SET
43
+ /\bDELETE\b.*\bFROM\b/i, // DELETE FROM
44
+ /\bDROP\b\s+\bTABLE\b/i, // DROP TABLE
45
+ /\bALTER\b\s+\bTABLE\b/i, // ALTER TABLE
46
+ /\bCREATE\b\s+\bTABLE\b/i, // CREATE TABLE
47
+ /\bEXEC\b\s+/i, // EXEC sp_...
48
+ /[=;*]\s*$/, // SQL operators at end (WHERE x = 1; or SELECT *)
49
+ ];
50
+ /** Scalar SQL types that do not accept array values */
51
+ const SCALAR_SQL_TYPES = new Set([
52
+ 'nvarchar', 'varchar', 'char', 'nchar', 'text', 'ntext',
53
+ 'int', 'bigint', 'smallint', 'tinyint',
54
+ 'decimal', 'numeric', 'float', 'real', 'money', 'smallmoney',
55
+ 'bit',
56
+ 'date', 'datetime', 'datetime2', 'smalldatetime', 'datetimeoffset', 'time',
57
+ 'uniqueidentifier',
58
+ 'string', 'number', 'boolean',
59
+ ]);
60
+ const DEFAULT_SUGGESTION = {
61
+ text: 'Use only valid properties for RunView/RunViews and RunQuery',
62
+ example: `// ❌ WRONG - Invalid properties on RunView:
63
+ await utilities.rv.RunView({
64
+ EntityName: 'MJ: AI Prompt Runs',
65
+ Parameters: { startDate, endDate }, // INVALID!
66
+ GroupBy: 'Status' // INVALID!
67
+ });
68
+
69
+ // ✅ CORRECT - Use ExtraFilter for WHERE clauses:
70
+ await utilities.rv.RunView({
71
+ EntityName: 'MJ: AI Prompt Runs',
72
+ ExtraFilter: \`RunAt >= '\${startDate.toISOString()}' AND RunAt <= '\${endDate.toISOString()}'\`,
73
+ OrderBy: 'RunAt DESC',
74
+ Fields: ['RunAt', 'Status', 'Success']
75
+ });
76
+
77
+ // ✅ For aggregations, use RunQuery with a pre-defined query:
78
+ await utilities.rq.RunQuery({
79
+ QueryName: 'Prompt Run Summary',
80
+ Parameters: { startDate, endDate } // Parameters ARE valid for RunQuery
81
+ });
82
+
83
+ // Valid RunView properties:
84
+ // - EntityName (required)
85
+ // - ExtraFilter, OrderBy, Fields, MaxRows, StartRow, ResultType (optional)
86
+
87
+ // Valid RunQuery properties:
88
+ // - QueryName (required)
89
+ // - CategoryPath, CategoryID, Parameters (optional)`,
90
+ };
91
+ // ── Callee matching ──────────────────────────────────────────────────
92
+ function isRunQueryCallee(callee) {
93
+ return (t.isMemberExpression(callee) &&
94
+ t.isMemberExpression(callee.object) &&
95
+ t.isIdentifier(callee.object.object) &&
96
+ callee.object.object.name === 'utilities' &&
97
+ t.isIdentifier(callee.object.property) &&
98
+ callee.object.property.name === 'rq' &&
99
+ t.isIdentifier(callee.property) &&
100
+ callee.property.name === 'RunQuery');
101
+ }
102
+ // ── useState init collector ──────────────────────────────────────────
103
+ function collectUseStateInits(ast) {
104
+ const stateInits = new Map();
105
+ traverse(ast, {
106
+ VariableDeclarator(path) {
107
+ if (!t.isArrayPattern(path.node.id))
108
+ return;
109
+ const init = path.node.init;
110
+ if (!init || !t.isCallExpression(init) || !t.isIdentifier(init.callee) || init.callee.name !== 'useState')
111
+ return;
112
+ const firstEl = path.node.id.elements[0];
113
+ if (!t.isIdentifier(firstEl))
114
+ return;
115
+ if (init.arguments.length > 0) {
116
+ const arg = init.arguments[0];
117
+ const category = getLiteralCategory(arg);
118
+ if (category && category !== 'null') {
119
+ let description;
120
+ if (t.isNumericLiteral(arg))
121
+ description = String(arg.value);
122
+ else if (t.isStringLiteral(arg))
123
+ description = `"${arg.value}"`;
124
+ else if (t.isBooleanLiteral(arg))
125
+ description = String(arg.value);
126
+ else
127
+ description = category;
128
+ stateInits.set(firstEl.name, { category, description });
129
+ }
130
+ }
131
+ },
132
+ noScope: true,
133
+ });
134
+ return stateInits;
135
+ }
136
+ function getLiteralCategory(node) {
137
+ if (t.isNumericLiteral(node))
138
+ return 'number';
139
+ if (t.isStringLiteral(node))
140
+ return 'string';
141
+ if (t.isBooleanLiteral(node))
142
+ return 'boolean';
143
+ if (t.isNullLiteral(node))
144
+ return 'null';
145
+ if (t.isTemplateLiteral(node))
146
+ return 'string';
147
+ return null;
148
+ }
149
+ function expectedJsCategory(paramType) {
150
+ if (!paramType)
151
+ return null;
152
+ const lower = paramType.toLowerCase().replace(/\(.*\)/, '').trim();
153
+ const numericTypes = new Set([
154
+ 'int', 'bigint', 'smallint', 'tinyint', 'decimal', 'numeric',
155
+ 'float', 'real', 'money', 'smallmoney', 'number',
156
+ ]);
157
+ const stringTypes = new Set([
158
+ 'nvarchar', 'varchar', 'char', 'nchar', 'text', 'ntext',
159
+ 'uniqueidentifier', 'string',
160
+ ]);
161
+ const boolTypes = new Set(['bit', 'boolean']);
162
+ if (numericTypes.has(lower))
163
+ return 'number';
164
+ if (stringTypes.has(lower))
165
+ return 'string';
166
+ if (boolTypes.has(lower))
167
+ return 'boolean';
168
+ return null;
169
+ }
170
+ // ── Invalid-property message builder ─────────────────────────────────
171
+ function buildInvalidRunQueryPropertyMessage(propName) {
172
+ switch (propName) {
173
+ case 'ExtraFilter':
174
+ return `RunQuery does not support 'ExtraFilter'. WHERE clauses should be in the pre-defined query or passed as Parameters.`;
175
+ case 'Fields':
176
+ return `RunQuery does not support 'Fields'. The query definition determines returned fields.`;
177
+ case 'OrderBy':
178
+ return `RunQuery does not support 'OrderBy'. ORDER BY should be in the query definition.`;
179
+ default:
180
+ return `Invalid property '${propName}' on RunQuery. Valid properties: ${Array.from(VALID_RUNQUERY_PROPS).join(', ')}`;
181
+ }
182
+ }
183
+ // ── Property type validation ─────────────────────────────────────────
184
+ function validateRunQueryPropertyType(propName, value, prop, violations) {
185
+ if (propName === 'QueryID' || propName === 'QueryName' || propName === 'CategoryID' || propName === 'CategoryPath') {
186
+ if (!isStringLike(value)) {
187
+ const exampleMap = {
188
+ QueryID: `"550e8400-e29b-41d4-a716-446655440000"`,
189
+ QueryName: `"Sales by Region"`,
190
+ CategoryID: `"123e4567-e89b-12d3-a456-426614174000"`,
191
+ CategoryPath: `"/Reports/Sales/"`,
192
+ };
193
+ violations.push({
194
+ rule: RULE_NAME,
195
+ severity: 'critical',
196
+ line: prop.loc?.start.line || 0,
197
+ column: prop.loc?.start.column || 0,
198
+ message: `RunQuery property '${propName}' must be a string. Example: ${propName}: ${exampleMap[propName] || '""'}`,
199
+ code: `${propName}: ${value.type === 'ObjectExpression' ? '{...}' : value.type === 'ArrayExpression' ? '[...]' : '...'}`,
200
+ suggestion: DEFAULT_SUGGESTION,
201
+ });
202
+ }
203
+ }
204
+ else if (propName === 'Parameters') {
205
+ if (!isObjectLike(value)) {
206
+ violations.push({
207
+ rule: RULE_NAME,
208
+ severity: 'critical',
209
+ line: prop.loc?.start.line || 0,
210
+ column: prop.loc?.start.column || 0,
211
+ message: `RunQuery property 'Parameters' must be an object containing key-value pairs. Example: Parameters: { startDate: '2024-01-01', status: 'Active' }`,
212
+ code: `Parameters: ${t.isArrayExpression(value) ? '[...]' : t.isStringLiteral(value) ? '"..."' : '...'}`,
213
+ suggestion: DEFAULT_SUGGESTION,
214
+ });
215
+ }
216
+ }
217
+ else if (propName === 'MaxRows' || propName === 'StartRow') {
218
+ if (!isNumberLike(value)) {
219
+ violations.push({
220
+ rule: RULE_NAME,
221
+ severity: 'critical',
222
+ line: prop.loc?.start.line || 0,
223
+ column: prop.loc?.start.column || 0,
224
+ message: `RunQuery property '${propName}' must be a number. Example: ${propName}: ${propName === 'MaxRows' ? '100' : '0'}`,
225
+ code: `${propName}: ${value.type === 'StringLiteral' ? '"..."' : value.type === 'ObjectExpression' ? '{...}' : '...'}`,
226
+ suggestion: DEFAULT_SUGGESTION,
227
+ });
228
+ }
229
+ }
230
+ }
231
+ // ── SQL injection detection ──────────────────────────────────────────
232
+ function detectSQLInjection(value, path, violations, knownQueryNames) {
233
+ if (t.isStringLiteral(value)) {
234
+ const queryName = value.value;
235
+ // Skip SQL check if the query name is a known registered query from the spec
236
+ if (knownQueryNames?.has(queryName))
237
+ return;
238
+ // Check for structural SQL patterns (require multiple keywords in combination
239
+ // to avoid false positives on domain terms like "Join Year", "Revenue From Events")
240
+ const looksLikeSQL = SQL_PATTERNS.some((pattern) => pattern.test(queryName));
241
+ if (looksLikeSQL) {
242
+ violations.push({
243
+ rule: RULE_NAME,
244
+ severity: 'critical',
245
+ line: value.loc?.start.line || 0,
246
+ column: value.loc?.start.column || 0,
247
+ message: `RunQuery cannot accept SQL statements. QueryName must be a registered query name, not SQL: "${queryName.substring(0, 50)}..."`,
248
+ code: value.value.substring(0, 100),
249
+ });
250
+ }
251
+ }
252
+ else if (t.isIdentifier(value) || t.isTemplateLiteral(value)) {
253
+ violations.push({
254
+ rule: RULE_NAME,
255
+ severity: 'medium',
256
+ line: value.loc?.start.line || 0,
257
+ column: value.loc?.start.column || 0,
258
+ message: `Dynamic QueryName detected. Ensure this is a query name, not a SQL statement.`,
259
+ code: path.toString().substring(0, 100),
260
+ });
261
+ }
262
+ }
263
+ // ── Query existence validation ───────────────────────────────────────
264
+ function validateQueryExistence(queryName, componentSpec, path, violations) {
265
+ if (!componentSpec?.dataRequirements?.queries)
266
+ return;
267
+ const queryExists = componentSpec.dataRequirements.queries.some((q) => q.name === queryName);
268
+ if (!queryExists) {
269
+ const availableQueries = componentSpec.dataRequirements.queries.map((q) => q.name).join(', ');
270
+ violations.push({
271
+ rule: RULE_NAME,
272
+ severity: 'high',
273
+ line: path.node.loc?.start.line || 0,
274
+ column: path.node.loc?.start.column || 0,
275
+ message: `Query '${queryName}' not found in component spec. Available queries: ${availableQueries || 'none'}`,
276
+ code: `QueryName: '${componentSpec.dataRequirements.queries[0]?.name || 'QueryNameFromSpec'}'`,
277
+ });
278
+ }
279
+ }
280
+ // ── CategoryPath validation ──────────────────────────────────────────
281
+ function validateCategoryPath(queryName, hasCategoryPath, queryNameProp, path, componentSpec, violations) {
282
+ if (!componentSpec?.dataRequirements?.queries || hasCategoryPath)
283
+ return;
284
+ const specQuery = componentSpec.dataRequirements.queries.find((q) => q.name === queryName);
285
+ if (!specQuery?.categoryPath || specQuery.categoryPath.trim().length === 0)
286
+ return;
287
+ const expectedCategoryPath = specQuery.categoryPath;
288
+ violations.push({
289
+ rule: RULE_NAME,
290
+ severity: 'critical',
291
+ line: queryNameProp?.loc?.start.line || path.node.loc?.start.line || 0,
292
+ column: queryNameProp?.loc?.start.column || path.node.loc?.start.column || 0,
293
+ message: `RunQuery with QueryName '${queryName}' is missing required CategoryPath parameter. Queries are uniquely identified by both QueryName and CategoryPath together. Without CategoryPath, RunQuery may find a different query with the same name, causing collisions and unintended behavior.`,
294
+ code: `RunQuery({ QueryName: '${queryName}' }) // Missing: CategoryPath`,
295
+ suggestion: {
296
+ text: `Add CategoryPath property to uniquely identify the query. The CategoryPath should match what's defined in your dataRequirements.queries[].categoryPath`,
297
+ example: `await utilities.rq.RunQuery({
298
+ QueryName: '${queryName}',
299
+ CategoryPath: '${expectedCategoryPath}', // Required: ensures correct query is used
300
+ Parameters: {
301
+ // Your query parameters here
302
+ }
303
+ })`,
304
+ },
305
+ });
306
+ }
307
+ // ── Parameters: array format ─────────────────────────────────────────
308
+ function validateParametersArray(paramValue, parametersNode, specQuery, violations) {
309
+ const arrayElements = paramValue.elements.filter((e) => t.isObjectExpression(e));
310
+ const paramPairs = [];
311
+ let isNameValueFormat = true;
312
+ for (const elem of arrayElements) {
313
+ let name = null;
314
+ let value = null;
315
+ for (const prop of elem.properties) {
316
+ if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
317
+ const propName = prop.key.name.toLowerCase();
318
+ if (propName === 'name' || propName === 'fieldname') {
319
+ if (t.isStringLiteral(prop.value))
320
+ name = prop.value.value;
321
+ else if (t.isIdentifier(prop.value))
322
+ name = prop.value.name;
323
+ }
324
+ else if (propName === 'value') {
325
+ if (t.isStringLiteral(prop.value))
326
+ value = `'${prop.value.value}'`;
327
+ else if (t.isNumericLiteral(prop.value))
328
+ value = prop.value.value;
329
+ else if (t.isBooleanLiteral(prop.value))
330
+ value = prop.value.value;
331
+ else if (t.isIdentifier(prop.value))
332
+ value = prop.value.name;
333
+ else
334
+ value = '/* value */';
335
+ }
336
+ }
337
+ }
338
+ if (name && value !== null) {
339
+ paramPairs.push({ name, value });
340
+ }
341
+ else {
342
+ isNameValueFormat = false;
343
+ break;
344
+ }
345
+ }
346
+ let fixMessage;
347
+ let fixCode;
348
+ if (isNameValueFormat && paramPairs.length > 0) {
349
+ const objProps = paramPairs.map((p) => ` ${p.name}: ${p.value}`).join(',\n');
350
+ fixCode = `Parameters: {\n${objProps}\n}`;
351
+ if (specQuery?.parameters) {
352
+ const specParamNames = specQuery.parameters.map((p) => p.name);
353
+ const providedNames = paramPairs.map((p) => p.name);
354
+ const missing = specParamNames.filter((n) => !providedNames.includes(n));
355
+ const extra = providedNames.filter((n) => !specParamNames.includes(n));
356
+ if (missing.length > 0 || extra.length > 0) {
357
+ fixMessage = `RunQuery Parameters must be object, not array. `;
358
+ if (missing.length > 0)
359
+ fixMessage += `Missing required: ${missing.join(', ')}. `;
360
+ if (extra.length > 0)
361
+ fixMessage += `Unknown params: ${extra.join(', ')}. `;
362
+ fixMessage += `Expected params from spec: ${specParamNames.join(', ')}`;
363
+ }
364
+ else {
365
+ fixMessage = `RunQuery Parameters must be object with key-value pairs, not array. Auto-fix: convert [{Name,Value}] to object format`;
366
+ }
367
+ }
368
+ else {
369
+ fixMessage = `RunQuery Parameters must be object with key-value pairs, not array of {Name/Value} objects`;
370
+ }
371
+ }
372
+ else {
373
+ if (specQuery?.parameters && specQuery.parameters.length > 0) {
374
+ const exampleParams = specQuery.parameters
375
+ .slice(0, 3)
376
+ .map((p) => ` ${p.name}: '${p.testValue || 'value'}'`)
377
+ .join(',\n');
378
+ fixCode = `Parameters: {\n${exampleParams}\n}`;
379
+ fixMessage = `RunQuery Parameters must be object. Expected params: ${specQuery.parameters.map((p) => p.name).join(', ')}`;
380
+ }
381
+ else {
382
+ fixCode = `Parameters: {\n paramName1: 'value1',\n paramName2: 'value2'\n}`;
383
+ fixMessage = `RunQuery Parameters must be object with key-value pairs, not array`;
384
+ }
385
+ }
386
+ violations.push({
387
+ rule: RULE_NAME,
388
+ severity: 'critical',
389
+ line: parametersNode.loc?.start.line || 0,
390
+ column: parametersNode.loc?.start.column || 0,
391
+ message: fixMessage,
392
+ code: fixCode,
393
+ });
394
+ }
395
+ // ── Parameters: object format (spec validation) ──────────────────────
396
+ function validateParametersObject(paramValue, parametersNode, queryName, specQuery, violations) {
397
+ if (!specQuery.parameters)
398
+ return;
399
+ const providedParamsMap = new Map();
400
+ for (const prop of paramValue.properties) {
401
+ if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
402
+ providedParamsMap.set(prop.key.name.toLowerCase(), prop.key.name);
403
+ }
404
+ }
405
+ const requiredParams = specQuery.parameters.filter((p) => {
406
+ return p.isRequired === true || p.value === '@runtime';
407
+ });
408
+ const specParamNames = specQuery.parameters.map((p) => p.name);
409
+ const specParamNamesLower = specParamNames.map((n) => n.toLowerCase());
410
+ const missing = requiredParams
411
+ .map((p) => p.name)
412
+ .filter((n) => !providedParamsMap.has(n.toLowerCase()));
413
+ const extra = Array.from(providedParamsMap.values()).filter((providedName) => !specParamNamesLower.includes(providedName.toLowerCase()));
414
+ if (missing.length > 0 || extra.length > 0) {
415
+ let message = `Query '${queryName}' parameter mismatch. `;
416
+ if (missing.length > 0)
417
+ message += `Missing: ${missing.join(', ')}. `;
418
+ if (extra.length > 0)
419
+ message += `Unknown: ${extra.join(', ')}. `;
420
+ const correctParams = specQuery.parameters
421
+ .map((p) => {
422
+ const providedName = providedParamsMap.get(p.name.toLowerCase());
423
+ if (providedName) {
424
+ const existingProp = paramValue.properties.find((prop) => t.isObjectProperty(prop) && t.isIdentifier(prop.key) && prop.key.name.toLowerCase() === p.name.toLowerCase());
425
+ if (existingProp && t.isStringLiteral(existingProp.value))
426
+ return ` ${p.name}: '${existingProp.value.value}'`;
427
+ if (existingProp && t.isNumericLiteral(existingProp.value))
428
+ return ` ${p.name}: ${existingProp.value.value}`;
429
+ if (existingProp && t.isIdentifier(existingProp.value))
430
+ return ` ${p.name}: ${existingProp.value.name}`;
431
+ }
432
+ return ` ${p.name}: '${p.testValue || 'value'}'`;
433
+ })
434
+ .join(',\n');
435
+ violations.push({
436
+ rule: RULE_NAME,
437
+ severity: 'high',
438
+ line: parametersNode.loc?.start.line || 0,
439
+ column: parametersNode.loc?.start.column || 0,
440
+ message: message + `Expected: {${specParamNames.join(', ')}}`,
441
+ code: `Parameters: {\n${correctParams}\n}`,
442
+ });
443
+ }
444
+ }
445
+ // ── Parameters: variable reference (TypeContext) ─────────────────────
446
+ function validateParametersVariable(paramValue, parametersNode, queryName, specQuery, typeContext, violations) {
447
+ if (!typeContext || !specQuery.parameters)
448
+ return;
449
+ const varType = typeContext.getVariableType(paramValue.name);
450
+ if (varType?.type !== 'object' || !varType.fields)
451
+ return;
452
+ const providedParamsLower = new Map();
453
+ for (const [fieldName] of varType.fields) {
454
+ providedParamsLower.set(fieldName.toLowerCase(), fieldName);
455
+ }
456
+ const specParamNames = specQuery.parameters.map((p) => p.name);
457
+ const specParamNamesLower = specParamNames.map((n) => n.toLowerCase());
458
+ const extra = Array.from(providedParamsLower.values()).filter((name) => !specParamNamesLower.includes(name.toLowerCase()));
459
+ if (extra.length > 0) {
460
+ violations.push({
461
+ rule: RULE_NAME,
462
+ severity: 'high',
463
+ line: parametersNode.loc?.start.line || 0,
464
+ column: parametersNode.loc?.start.column || 0,
465
+ message: `Query '${queryName}' has unknown parameters: ${extra.join(', ')}. Expected: {${specParamNames.join(', ')}}`,
466
+ code: `Parameters: ${paramValue.name}`,
467
+ });
468
+ }
469
+ }
470
+ // ── Parameters: other invalid type ───────────────────────────────────
471
+ function validateParametersOtherType(parametersNode, specQuery, violations) {
472
+ let fixCode;
473
+ let message;
474
+ if (specQuery?.parameters && specQuery.parameters.length > 0) {
475
+ const exampleParams = specQuery.parameters.map((p) => ` ${p.name}: '${p.testValue || 'value'}'`).join(',\n');
476
+ fixCode = `Parameters: {\n${exampleParams}\n}`;
477
+ message = `RunQuery Parameters must be object. Expected params from spec: ${specQuery.parameters.map((p) => p.name).join(', ')}`;
478
+ }
479
+ else {
480
+ fixCode = `Parameters: {\n paramName: 'value'\n}`;
481
+ message = `RunQuery Parameters must be object with key-value pairs`;
482
+ }
483
+ violations.push({
484
+ rule: RULE_NAME,
485
+ severity: 'critical',
486
+ line: parametersNode.loc?.start.line || 0,
487
+ column: parametersNode.loc?.start.column || 0,
488
+ message,
489
+ code: fixCode,
490
+ });
491
+ }
492
+ // ── Parameter value type validation ──────────────────────────────────
493
+ function validateParameterValueTypes(parametersNode, queryName, componentSpec, violations) {
494
+ const querySpec = componentSpec.dataRequirements?.queries?.find((q) => q.name === queryName);
495
+ if (!querySpec?.parameters)
496
+ return;
497
+ // Build type map
498
+ const paramTypes = new Map();
499
+ for (const param of querySpec.parameters) {
500
+ const extParam = param;
501
+ if (extParam.type) {
502
+ paramTypes.set(param.name.toLowerCase(), {
503
+ type: mapSQLTypeToJSType(extParam.type),
504
+ sqlType: extParam.type,
505
+ });
506
+ }
507
+ }
508
+ if (paramTypes.size === 0)
509
+ return;
510
+ for (const prop of parametersNode.properties) {
511
+ if (!t.isObjectProperty(prop) || !t.isIdentifier(prop.key))
512
+ continue;
513
+ const paramName = prop.key.name;
514
+ const paramTypeInfo = paramTypes.get(paramName.toLowerCase());
515
+ if (!paramTypeInfo)
516
+ continue;
517
+ const expectedType = paramTypeInfo.type;
518
+ let actualType = null;
519
+ let valueDesc = '';
520
+ if (t.isStringLiteral(prop.value)) {
521
+ actualType = 'string';
522
+ valueDesc = `'${prop.value.value}'`;
523
+ }
524
+ else if (t.isNumericLiteral(prop.value)) {
525
+ actualType = 'number';
526
+ valueDesc = String(prop.value.value);
527
+ }
528
+ else if (t.isBooleanLiteral(prop.value)) {
529
+ actualType = 'boolean';
530
+ valueDesc = String(prop.value.value);
531
+ }
532
+ else if (t.isNullLiteral(prop.value)) {
533
+ actualType = 'null';
534
+ valueDesc = 'null';
535
+ }
536
+ else if (t.isIdentifier(prop.value)) {
537
+ continue;
538
+ } // Variable - skip
539
+ else if (t.isTemplateLiteral(prop.value)) {
540
+ actualType = 'string';
541
+ valueDesc = 'template string';
542
+ }
543
+ else {
544
+ continue;
545
+ } // Complex expression - skip
546
+ if (actualType && actualType !== expectedType) {
547
+ if (actualType === 'null')
548
+ continue; // Allow null for nullable params
549
+ let suggestion = '';
550
+ if (expectedType === 'number' && actualType === 'string') {
551
+ if (t.isStringLiteral(prop.value) && !isNaN(Number(prop.value.value))) {
552
+ suggestion = `Use ${paramName}: ${prop.value.value} (without quotes)`;
553
+ }
554
+ else {
555
+ suggestion = `Use a numeric value`;
556
+ }
557
+ }
558
+ else if (expectedType === 'boolean' && actualType === 'string') {
559
+ if (t.isStringLiteral(prop.value)) {
560
+ const val = prop.value.value.toLowerCase();
561
+ if (val === 'true' || val === 'false') {
562
+ suggestion = `Use ${paramName}: ${val} (without quotes)`;
563
+ }
564
+ else {
565
+ suggestion = `Use ${paramName}: true or ${paramName}: false`;
566
+ }
567
+ }
568
+ }
569
+ else if (expectedType === 'string' && actualType === 'number') {
570
+ suggestion = `Use ${paramName}: '${valueDesc}'`;
571
+ }
572
+ violations.push({
573
+ rule: RULE_NAME,
574
+ severity: 'high',
575
+ line: prop.loc?.start.line || 0,
576
+ column: prop.loc?.start.column || 0,
577
+ message: `Parameter "${paramName}" has wrong type. Expected ${expectedType} (${paramTypeInfo.sqlType}), got ${actualType} (${valueDesc}).${suggestion ? ' ' + suggestion : ''}`,
578
+ code: suggestion || `${paramName}: <${expectedType} value>`,
579
+ });
580
+ }
581
+ }
582
+ }
583
+ // ── Null/array/useState per-param checks ─────────────────────────────
584
+ function validateIndividualParamValues(parametersNode, queryName, componentSpec, stateInits, violations) {
585
+ const querySpec = componentSpec.dataRequirements?.queries?.find((q) => q.name === queryName);
586
+ if (!querySpec?.parameters)
587
+ return;
588
+ const specParamMap = new Map();
589
+ for (const p of querySpec.parameters) {
590
+ specParamMap.set(p.name.toLowerCase(), p);
591
+ }
592
+ for (const prop of parametersNode.properties) {
593
+ if (!t.isObjectProperty(prop) || !t.isIdentifier(prop.key))
594
+ continue;
595
+ const paramName = prop.key.name;
596
+ const specParam = specParamMap.get(paramName.toLowerCase());
597
+ if (!specParam)
598
+ continue;
599
+ const value = prop.value;
600
+ const isRequired = specParam.isRequired || specParam.value === '@runtime';
601
+ // Check: null literal on required parameter
602
+ if (t.isNullLiteral(value) && isRequired) {
603
+ violations.push({
604
+ rule: RULE_NAME,
605
+ severity: 'high',
606
+ line: prop.loc?.start.line ?? 0,
607
+ column: prop.loc?.start.column ?? 0,
608
+ message: `Required query parameter "${paramName}" is set to null. This will cause the query to fail or return unexpected results.`,
609
+ code: `${paramName}: null`,
610
+ suggestion: {
611
+ text: `Provide a valid value for "${paramName}" or add a null guard before calling RunQuery`,
612
+ example: `${paramName}: ${specParam.testValue ? `'${specParam.testValue}'` : "'value'"}`,
613
+ },
614
+ });
615
+ continue;
616
+ }
617
+ // Check: array expression for scalar parameter
618
+ if (t.isArrayExpression(value)) {
619
+ const paramType = specParam.type?.toLowerCase().replace(/\(.*\)/, '').trim();
620
+ if (!paramType || SCALAR_SQL_TYPES.has(paramType)) {
621
+ violations.push({
622
+ rule: RULE_NAME,
623
+ severity: 'high',
624
+ line: prop.loc?.start.line ?? 0,
625
+ column: prop.loc?.start.column ?? 0,
626
+ message: `Query parameter "${paramName}" expects a scalar value (type: ${specParam.type ?? 'scalar'}) but received an array. Pass a single value instead.`,
627
+ code: `${paramName}: [...]`,
628
+ suggestion: {
629
+ text: `Pass a single value instead of an array`,
630
+ example: `${paramName}: ${specParam.testValue ? `'${specParam.testValue}'` : "'value'"}`,
631
+ },
632
+ });
633
+ }
634
+ continue;
635
+ }
636
+ // Check: useState variable with mismatched init type
637
+ if (t.isIdentifier(value)) {
638
+ const stateInfo = stateInits.get(value.name);
639
+ if (!stateInfo)
640
+ continue;
641
+ const expectedCategory = expectedJsCategory(specParam.type);
642
+ if (!expectedCategory)
643
+ continue;
644
+ if (stateInfo.category !== expectedCategory) {
645
+ violations.push({
646
+ rule: RULE_NAME,
647
+ severity: 'high',
648
+ line: prop.loc?.start.line ?? 0,
649
+ column: prop.loc?.start.column ?? 0,
650
+ message: `Query parameter "${paramName}" expects type "${specParam.type}" (${expectedCategory}) but state variable "${value.name}" is initialized as ${stateInfo.category} (${stateInfo.description}). This type mismatch may cause the query to fail.`,
651
+ code: `${paramName}: ${value.name}`,
652
+ suggestion: {
653
+ text: `Initialize the state variable with a ${expectedCategory} value, or convert before passing`,
654
+ example: expectedCategory === 'number'
655
+ ? `useState(0)`
656
+ : expectedCategory === 'string'
657
+ ? `useState('')`
658
+ : `useState(false)`,
659
+ },
660
+ });
661
+ }
662
+ }
663
+ }
664
+ }
665
+ // ── Missing required Parameters property ─────────────────────────────
666
+ function validateMissingParametersProperty(queryName, specQuery, path, violations) {
667
+ if (!specQuery?.parameters || specQuery.parameters.length === 0)
668
+ return;
669
+ const requiredParams = specQuery.parameters.filter((p) => {
670
+ return p.isRequired === true || p.value === '@runtime';
671
+ });
672
+ if (requiredParams.length > 0) {
673
+ const paramNames = requiredParams.map((p) => p.name).join(', ');
674
+ const exampleParams = requiredParams.map((p) => ` ${p.name}: ${p.testValue ? `'${p.testValue}'` : "'value'"}`).join(',\n');
675
+ violations.push({
676
+ rule: RULE_NAME,
677
+ severity: 'high',
678
+ line: path.node.loc?.start.line || 0,
679
+ column: path.node.loc?.start.column || 0,
680
+ message: `Query '${queryName}' requires parameters but RunQuery call is missing 'Parameters' property. Required: ${paramNames}`,
681
+ code: `Parameters: {\n${exampleParams}\n}`,
682
+ });
683
+ }
684
+ }
685
+ // ── Main Rule ────────────────────────────────────────────────────────
686
+ let RunQueryCallValidationRule = class RunQueryCallValidationRule extends BaseLintRule {
687
+ get Name() { return 'runquery-call-validation'; }
688
+ get AppliesTo() { return 'all'; }
689
+ Test(ast, _componentName, componentSpec, _options, typeContext) {
690
+ const violations = [];
691
+ // Pre-collect useState initializers for type checking
692
+ const stateInits = collectUseStateInits(ast);
693
+ traverse(ast, {
694
+ CallExpression(path) {
695
+ if (!isRunQueryCallee(path.node.callee))
696
+ return;
697
+ // A. Argument structure checks
698
+ if (!path.node.arguments[0]) {
699
+ violations.push({
700
+ rule: RULE_NAME,
701
+ severity: 'critical',
702
+ line: path.node.loc?.start.line || 0,
703
+ column: path.node.loc?.start.column || 0,
704
+ message: `RunQuery requires a RunQueryParams object as the first parameter.
705
+ Use: RunQuery({
706
+ QueryName: 'YourQuery', // Or use QueryID: 'uuid'
707
+ CategoryPath: 'Category/Subcategory', // Optional. Used when QueryName is provided to provide a better filter
708
+ Parameters: { // Optional query parameters
709
+ param1: 'value1'
710
+ },
711
+ StartRow: 0, // Optional offset (0-based)
712
+ MaxRows: 100 // Optional limit
713
+ })`,
714
+ code: `RunQuery()`,
715
+ suggestion: DEFAULT_SUGGESTION,
716
+ });
717
+ return;
718
+ }
719
+ if (t.isIdentifier(path.node.arguments[0]))
720
+ return; // Variable — skip
721
+ if (!t.isObjectExpression(path.node.arguments[0])) {
722
+ const argType = t.isStringLiteral(path.node.arguments[0]) ? 'string' : 'non-object';
723
+ violations.push({
724
+ rule: RULE_NAME,
725
+ severity: 'critical',
726
+ line: path.node.arguments[0].loc?.start.line || 0,
727
+ column: path.node.arguments[0].loc?.start.column || 0,
728
+ message: `RunQuery expects a RunQueryParams object, not a ${argType}.
729
+ Use: RunQuery({
730
+ QueryName: 'YourQuery', // Or use QueryID: 'uuid'
731
+ CategoryPath: 'Category/Subcategory', // Optional. Used when QueryName is provided to provide a better filter
732
+ Parameters: { // Optional query parameters
733
+ startDate: '2024-01-01',
734
+ endDate: '2024-12-31'
735
+ },
736
+ StartRow: 0, // Optional offset (0-based)
737
+ MaxRows: 100 // Optional limit
738
+ })
739
+ Valid properties: QueryID, QueryName, CategoryID, CategoryPath, Parameters, MaxRows, StartRow, ForceAuditLog, AuditLogDescription`,
740
+ code: path.toString().substring(0, 100),
741
+ suggestion: DEFAULT_SUGGESTION,
742
+ });
743
+ return;
744
+ }
745
+ const config = path.node.arguments[0];
746
+ // B. Extract properties and validate
747
+ let hasQueryID = false;
748
+ let hasQueryName = false;
749
+ let hasCategoryPath = false;
750
+ let queryName = null;
751
+ let parametersNode = null;
752
+ let queryNameProp;
753
+ const foundProps = [];
754
+ for (const prop of config.properties) {
755
+ if (!t.isObjectProperty(prop) || !t.isIdentifier(prop.key))
756
+ continue;
757
+ const propName = prop.key.name;
758
+ foundProps.push(propName);
759
+ if (propName === 'QueryID')
760
+ hasQueryID = true;
761
+ if (propName === 'QueryName') {
762
+ hasQueryName = true;
763
+ queryNameProp = prop;
764
+ if (t.isStringLiteral(prop.value))
765
+ queryName = prop.value.value;
766
+ }
767
+ if (propName === 'CategoryPath')
768
+ hasCategoryPath = true;
769
+ if (propName === 'Parameters')
770
+ parametersNode = prop;
771
+ // Check invalid property names
772
+ if (!VALID_RUNQUERY_PROPS.has(propName)) {
773
+ violations.push({
774
+ rule: RULE_NAME,
775
+ severity: 'critical',
776
+ line: prop.loc?.start.line || 0,
777
+ column: prop.loc?.start.column || 0,
778
+ message: buildInvalidRunQueryPropertyMessage(propName),
779
+ code: `${propName}: ...`,
780
+ suggestion: DEFAULT_SUGGESTION,
781
+ });
782
+ }
783
+ else {
784
+ // Validate property types
785
+ validateRunQueryPropertyType(propName, prop.value, prop, violations);
786
+ }
787
+ }
788
+ // Must have QueryID or QueryName
789
+ if (!hasQueryID && !hasQueryName) {
790
+ const propsContext = foundProps.length > 0 ? ` Found properties: ${foundProps.join(', ')}.` : '';
791
+ const message = hasCategoryPath
792
+ ? `RunQuery requires QueryName (or QueryID). CategoryPath alone is insufficient - it's only used to help filter when QueryName is ambiguous.${propsContext}`
793
+ : `RunQuery requires either QueryID or QueryName property to identify which query to run.${propsContext}`;
794
+ const exampleQueryName = componentSpec?.dataRequirements?.queries?.[0]?.name || 'YourQueryName';
795
+ violations.push({
796
+ rule: RULE_NAME,
797
+ severity: 'critical',
798
+ line: config.loc?.start.line || 0,
799
+ column: config.loc?.start.column || 0,
800
+ message,
801
+ code: `RunQuery({ QueryName: '${exampleQueryName}', ... })`,
802
+ suggestion: {
803
+ text: 'Add QueryName property to identify the query',
804
+ example: `await utilities.rq.RunQuery({\n QueryName: '${exampleQueryName}',${hasCategoryPath ? "\n CategoryPath: '...', // Optional, helps disambiguate" : ''}\n Parameters: { ... } // Optional query parameters\n})`,
805
+ },
806
+ });
807
+ }
808
+ // CategoryPath without QueryName — specific anti-pattern
809
+ if (!hasQueryID && !hasQueryName && hasCategoryPath) {
810
+ const exampleQueryName = componentSpec?.dataRequirements?.queries?.[0]?.name || 'YourQueryName';
811
+ const categoryPathProp = config.properties.find((p) => t.isObjectProperty(p) && t.isIdentifier(p.key) && p.key.name === 'CategoryPath');
812
+ violations.push({
813
+ rule: RULE_NAME,
814
+ severity: 'critical',
815
+ line: categoryPathProp?.loc?.start.line || config.loc?.start.line || 0,
816
+ column: categoryPathProp?.loc?.start.column || config.loc?.start.column || 0,
817
+ message: `CategoryPath cannot be used alone - it requires QueryName. CategoryPath is only used to disambiguate when multiple queries share the same name. You must specify which query to run using QueryName.`,
818
+ code: `CategoryPath: '...' // Missing: QueryName`,
819
+ suggestion: {
820
+ text: 'Add QueryName property alongside CategoryPath. The query name should come from your dataRequirements.queries[].name',
821
+ example: `// Query name from your spec: "${exampleQueryName}"\nawait utilities.rq.RunQuery({\n QueryName: '${exampleQueryName}', // Required: identifies which query to run\n CategoryPath: '...', // Optional: helps disambiguate if multiple queries have same name\n Parameters: {\n // Your query parameters here\n }\n})`,
822
+ },
823
+ });
824
+ }
825
+ // C. Query existence + SQL injection detection
826
+ const knownQueryNames = new Set(componentSpec?.dataRequirements?.queries?.map(q => q.name).filter(Boolean) ?? []);
827
+ if (queryName) {
828
+ validateQueryExistence(queryName, componentSpec, path, violations);
829
+ if (queryNameProp) {
830
+ detectSQLInjection(queryNameProp.value, path, violations, knownQueryNames);
831
+ }
832
+ }
833
+ else if (hasQueryName && queryNameProp) {
834
+ // Dynamic query name — still check for SQL injection
835
+ detectSQLInjection(queryNameProp.value, path, violations, knownQueryNames);
836
+ }
837
+ // D. CategoryPath missing when spec requires it
838
+ if (queryName) {
839
+ validateCategoryPath(queryName, hasCategoryPath, queryNameProp, path, componentSpec, violations);
840
+ }
841
+ // E. Parameters validation
842
+ if (!parametersNode) {
843
+ // Check if missing Parameters is a problem
844
+ if (queryName) {
845
+ const specQuery = componentSpec?.dataRequirements?.queries?.find((q) => q.name === queryName);
846
+ validateMissingParametersProperty(queryName, specQuery, path, violations);
847
+ }
848
+ return;
849
+ }
850
+ const paramValue = parametersNode.value;
851
+ const specQuery = queryName
852
+ ? componentSpec?.dataRequirements?.queries?.find((q) => q.name === queryName)
853
+ : undefined;
854
+ if (t.isArrayExpression(paramValue)) {
855
+ validateParametersArray(paramValue, parametersNode, specQuery, violations);
856
+ }
857
+ else if (t.isObjectExpression(paramValue)) {
858
+ // Validate param names against spec
859
+ if (specQuery) {
860
+ validateParametersObject(paramValue, parametersNode, queryName, specQuery, violations);
861
+ }
862
+ // Validate parameter value types
863
+ if (queryName && componentSpec) {
864
+ validateParameterValueTypes(paramValue, queryName, componentSpec, violations);
865
+ validateIndividualParamValues(paramValue, queryName, componentSpec, stateInits, violations);
866
+ }
867
+ }
868
+ else if (t.isIdentifier(paramValue)) {
869
+ if (specQuery && queryName) {
870
+ validateParametersVariable(paramValue, parametersNode, queryName, specQuery, typeContext, violations);
871
+ }
872
+ }
873
+ else {
874
+ // Other invalid type
875
+ validateParametersOtherType(parametersNode, specQuery, violations);
876
+ }
877
+ },
878
+ });
879
+ return violations;
880
+ }
881
+ };
882
+ RunQueryCallValidationRule = __decorate([
883
+ RegisterClass(BaseLintRule, 'runquery-call-validation')
884
+ ], RunQueryCallValidationRule);
885
+ export { RunQueryCallValidationRule };
886
+ //# sourceMappingURL=runquery-call-validation.js.map