@nitra/cursor 3.22.0 → 3.23.1

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 (229) hide show
  1. package/.pi-template/extensions/n-cursor-adr/docs/index.md +181 -0
  2. package/AGENTS.template.md +4 -0
  3. package/CHANGELOG.md +37 -3
  4. package/bin/docs/n-cursor.md +636 -0
  5. package/bin/docs/rename-yaml-extensions.md +207 -0
  6. package/bin/n-cursor.js +30 -3
  7. package/package.json +1 -1
  8. package/rules/abie/docs/fix.md +18 -0
  9. package/rules/abie/js/docs/applies.md +26 -0
  10. package/rules/abie/js/docs/env_dns.md +32 -0
  11. package/rules/abie/js/docs/firebase_hosting.md +23 -0
  12. package/rules/abie/js/docs/hc_pairing.md +35 -0
  13. package/rules/abie/js/docs/ua_http_route.md +28 -0
  14. package/rules/abie/js/docs/ua_node_selector.md +28 -0
  15. package/rules/abie/lib/docs/enabled.md +29 -0
  16. package/rules/abie/lib/docs/env-dns.md +35 -0
  17. package/rules/abie/lib/docs/hc-yaml.md +33 -0
  18. package/rules/abie/lib/docs/http-route.md +44 -0
  19. package/rules/abie/lib/docs/k8s-tree.md +40 -0
  20. package/rules/abie/lib/docs/kustomization-patches.md +47 -0
  21. package/rules/abie/lib/docs/overlay-paths.md +38 -0
  22. package/rules/abie/lib/docs/yaml.md +29 -0
  23. package/rules/adr/docs/fix.md +148 -0
  24. package/rules/adr/js/docs/hooks.md +259 -0
  25. package/rules/bun/docs/fix.md +156 -0
  26. package/rules/bun/js/docs/layout.md +393 -0
  27. package/rules/capacitor/docs/fix.md +121 -0
  28. package/rules/capacitor/js/docs/platforms.md +295 -0
  29. package/rules/changelog/changelog.mdc +4 -2
  30. package/rules/changelog/docs/fix.md +174 -0
  31. package/rules/changelog/js/consistency.mjs +114 -13
  32. package/rules/changelog/js/docs/consistency.md +387 -0
  33. package/rules/changelog/lib/docs/package-manifest.md +210 -0
  34. package/rules/ci4/docs/fix.md +179 -0
  35. package/rules/ci4/js/docs/marksman_config.md +128 -0
  36. package/rules/docker/docker.mdc +8 -3
  37. package/rules/docker/docs/fix.md +171 -0
  38. package/rules/docker/js/docs/lint.md +258 -0
  39. package/rules/docker/lib/docs/docker-hadolint.md +184 -0
  40. package/rules/docker/lib/docs/docker-mirror.md +247 -0
  41. package/rules/docker/lib/docs/docker-native-addon.md +170 -0
  42. package/rules/docker/lib/docs/docker-nginx-user.md +219 -0
  43. package/rules/docker/lint/docs/lint.md +193 -0
  44. package/rules/efes/docs/fix.md +203 -0
  45. package/rules/feedback/docs/fix.md +140 -0
  46. package/rules/flow/docs/fix.md +152 -0
  47. package/rules/ga/docs/fix.md +158 -0
  48. package/rules/ga/js/docs/lint.md +100 -0
  49. package/rules/ga/js/docs/workflows.md +217 -0
  50. package/rules/ga/lint/docs/lint.md +209 -0
  51. package/rules/ga/policy/clean_merged_branch/clean_merged_branch.rego +11 -2
  52. package/rules/ga/policy/clean_merged_branch/template/clean-merged-branch.yml.snippet.yml +3 -4
  53. package/rules/graphql/docs/fix.md +126 -0
  54. package/rules/graphql/js/docs/tooling.md +264 -0
  55. package/rules/graphql/lib/docs/graphql-gql-scan.md +219 -0
  56. package/rules/hasura/docs/fix.md +120 -0
  57. package/rules/hasura/hasura.mdc +14 -0
  58. package/rules/hasura/js/docs/internal_urls.md +326 -0
  59. package/rules/image-avif/docs/fix.md +132 -0
  60. package/rules/image-avif/js/docs/avif_generation.md +241 -0
  61. package/rules/image-compress/docs/fix.md +150 -0
  62. package/rules/image-compress/js/docs/package_setup.md +191 -0
  63. package/rules/js-bun-db/docs/fix.md +148 -0
  64. package/rules/js-bun-db/js/docs/safety.md +231 -0
  65. package/rules/js-bun-db/js-bun-db.mdc +42 -13
  66. package/rules/js-bun-db/lib/docs/bun-sql-scan.md +347 -0
  67. package/rules/js-bun-redis/docs/fix.md +123 -0
  68. package/rules/js-bun-redis/js/docs/imports.md +176 -0
  69. package/rules/js-bun-redis/lib/docs/redis-imports.md +223 -0
  70. package/rules/js-lint/docs/fix.md +117 -0
  71. package/rules/js-lint/js/docs/lint.md +250 -0
  72. package/rules/js-lint/js/docs/tooling.md +348 -0
  73. package/rules/js-lint/js/docs/utils_imports.md +207 -0
  74. package/rules/js-lint-ci/docs/fix.md +154 -0
  75. package/rules/js-lint-ci/js/docs/lint.md +144 -0
  76. package/rules/js-mssql/docs/fix.md +128 -0
  77. package/rules/js-mssql/js/docs/deps.md +263 -0
  78. package/rules/js-mssql/lib/docs/mssql-pool-scan.md +367 -0
  79. package/rules/js-run/docs/fix.md +144 -0
  80. package/rules/js-run/js/docs/runtime.md +388 -0
  81. package/rules/js-run/lib/docs/bunyan-imports.md +117 -0
  82. package/rules/js-run/lib/docs/check-env-scan.md +433 -0
  83. package/rules/js-run/lib/docs/conn-file-rules.md +300 -0
  84. package/rules/js-run/lib/docs/conn-imports-scan.md +204 -0
  85. package/rules/js-run/lib/docs/promise-settimeout-scan.md +326 -0
  86. package/rules/k8s/docs/fix.md +129 -0
  87. package/rules/k8s/js/docs/manifests.md +344 -0
  88. package/rules/k8s/js/manifests.mjs +6 -2
  89. package/rules/k8s/k8s.mdc +4 -2
  90. package/rules/k8s/lint/docs/lint.md +411 -0
  91. package/rules/k8s/policy/network_policy/template/deployment.snippet.yaml +2 -0
  92. package/rules/k8s/policy/network_policy/template/stateful-set.snippet.yaml +2 -0
  93. package/rules/nginx-default-tpl/docs/fix.md +124 -0
  94. package/rules/nginx-default-tpl/js/docs/template.md +378 -0
  95. package/rules/npm-module/docs/fix.md +98 -0
  96. package/rules/npm-module/js/docs/package_structure.md +274 -0
  97. package/rules/npm-module/js/docs/rule_meta.md +137 -0
  98. package/rules/npm-module/js/docs/skill_meta.md +190 -0
  99. package/rules/php/docs/fix.md +107 -0
  100. package/rules/php/js/docs/tooling.md +152 -0
  101. package/rules/php/lint/docs/lint.md +215 -0
  102. package/rules/python/docs/fix.md +163 -0
  103. package/rules/python/js/docs/applies.md +108 -0
  104. package/rules/python/js/docs/tooling.md +153 -0
  105. package/rules/python/lint/docs/lint.md +322 -0
  106. package/rules/rego/docs/fix.md +121 -0
  107. package/rules/rego/js/docs/applies.md +174 -0
  108. package/rules/rego/js/docs/lint.md +118 -0
  109. package/rules/rego/lint/docs/lint.md +204 -0
  110. package/rules/release/docs/change.md +185 -0
  111. package/rules/release/docs/fix.md +119 -0
  112. package/rules/release/docs/release.md +222 -0
  113. package/rules/release/lib/docs/aggregate.md +246 -0
  114. package/rules/release/lib/docs/change-file.md +200 -0
  115. package/rules/release/lib/docs/fallback.md +203 -0
  116. package/rules/rust/docs/fix.md +129 -0
  117. package/rules/rust/js/docs/applies.md +140 -0
  118. package/rules/rust/lib/docs/has-cargo-toml.md +130 -0
  119. package/rules/security/docs/fix.md +86 -0
  120. package/rules/security/js/docs/lint.md +171 -0
  121. package/rules/security/js/docs/sample_secret.md +190 -0
  122. package/rules/security/js/docs/trufflehog.md +137 -0
  123. package/rules/security/js/lint.mjs +9 -1
  124. package/rules/style-lint/docs/fix.md +155 -0
  125. package/rules/style-lint/js/docs/lint.md +184 -0
  126. package/rules/style-lint/js/docs/tooling.md +194 -0
  127. package/rules/tauri/docs/fix.md +158 -0
  128. package/rules/tauri/js/docs/cargo_mutants_config.md +168 -0
  129. package/rules/tauri/js/docs/tooling.md +228 -0
  130. package/rules/test/coverage/coverage.mjs +15 -3
  131. package/rules/test/docs/fix.md +132 -0
  132. package/rules/test/js/data/stryker_config/docs/stryker-vue-macros-ignorer.md +138 -0
  133. package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +134 -0
  134. package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +160 -0
  135. package/rules/test/js/data/vitest_config/docs/vitest.config.baseline.md +195 -0
  136. package/rules/test/js/docs/cargo_mutants_config.md +173 -0
  137. package/rules/test/js/docs/location.md +136 -0
  138. package/rules/test/js/docs/no-process-chdir.md +160 -0
  139. package/rules/test/js/docs/no-relative-fs-path.md +271 -0
  140. package/rules/test/js/docs/stryker_config.md +152 -0
  141. package/rules/test/js/docs/vitest-config-pool-forks.md +174 -0
  142. package/rules/text/docs/fix.md +118 -0
  143. package/rules/text/js/docs/forbidden-prettier.md +143 -0
  144. package/rules/text/js/docs/formatting.md +256 -0
  145. package/rules/text/js/docs/lint.md +122 -0
  146. package/rules/text/lint/docs/lint.md +220 -0
  147. package/rules/text/lint/docs/run-dotenv-linter.md +157 -0
  148. package/rules/text/lint/docs/run-shellcheck.md +212 -0
  149. package/rules/text/lint/docs/run-v8r.md +197 -0
  150. package/rules/vue/docs/fix.md +127 -0
  151. package/rules/vue/js/docs/packages.md +335 -0
  152. package/rules/vue/lib/docs/vue-forbidden-imports.md +261 -0
  153. package/rules/worktree/docs/fix.md +161 -0
  154. package/schemas/rule-meta.json +5 -1
  155. package/scripts/auto-rules.mjs +7 -4
  156. package/scripts/coverage-classify/docs/apply.md +202 -0
  157. package/scripts/coverage-classify/docs/cache.md +203 -0
  158. package/scripts/coverage-classify/docs/index.md +218 -0
  159. package/scripts/coverage-classify/docs/prompt.md +132 -0
  160. package/scripts/coverage-classify/docs/verdict-schema.md +169 -0
  161. package/scripts/coverage-fix-extract.mjs +122 -0
  162. package/scripts/coverage-fix.mjs +1 -1
  163. package/scripts/dispatcher/docs/graph.md +346 -0
  164. package/scripts/dispatcher/docs/index.md +236 -0
  165. package/scripts/dispatcher/docs/trace.md +296 -0
  166. package/scripts/dispatcher/index.mjs +1 -1
  167. package/scripts/dispatcher/lib/active.mjs +4 -8
  168. package/scripts/dispatcher/lib/commands.mjs +7 -11
  169. package/scripts/dispatcher/lib/docs/active.md +348 -0
  170. package/scripts/dispatcher/lib/docs/artifact.md +232 -0
  171. package/scripts/dispatcher/lib/docs/budget.md +167 -0
  172. package/scripts/dispatcher/lib/docs/capability.md +196 -0
  173. package/scripts/dispatcher/lib/docs/commands.md +210 -0
  174. package/scripts/dispatcher/lib/docs/events.md +182 -0
  175. package/scripts/dispatcher/lib/docs/executor.md +190 -0
  176. package/scripts/dispatcher/lib/docs/flow-lock.md +161 -0
  177. package/scripts/dispatcher/lib/docs/flow-resolve.md +267 -0
  178. package/scripts/dispatcher/lib/docs/gate.md +231 -0
  179. package/scripts/dispatcher/lib/docs/level.md +335 -0
  180. package/scripts/dispatcher/lib/docs/plan-panel.md +181 -0
  181. package/scripts/dispatcher/lib/docs/plan.md +200 -0
  182. package/scripts/dispatcher/lib/docs/planner.md +269 -0
  183. package/scripts/dispatcher/lib/docs/review.md +255 -0
  184. package/scripts/dispatcher/lib/docs/reviewer.md +240 -0
  185. package/scripts/dispatcher/lib/docs/snapshot.md +247 -0
  186. package/scripts/dispatcher/lib/docs/spec.md +203 -0
  187. package/scripts/dispatcher/lib/docs/state-store.md +303 -0
  188. package/scripts/dispatcher/lib/docs/subagent-runner.md +173 -0
  189. package/scripts/dispatcher/lib/executor.mjs +6 -1
  190. package/scripts/dispatcher/lib/flow-resolve.mjs +3 -1
  191. package/scripts/dispatcher/lib/level.mjs +29 -3
  192. package/scripts/dispatcher/lib/review.mjs +1 -1
  193. package/scripts/dispatcher/lib/subagent-runner.mjs +5 -3
  194. package/scripts/docs/auto-rules.md +376 -0
  195. package/scripts/docs/auto-skills.md +173 -0
  196. package/scripts/docs/build-agents-commands.md +183 -0
  197. package/scripts/docs/cli-entry.md +153 -0
  198. package/scripts/docs/coverage-fix.md +177 -0
  199. package/scripts/docs/ensure-nitra-cursor-dev-dependencies.md +189 -0
  200. package/scripts/lib/changed-files.mjs +4 -1
  201. package/scripts/lib/docs/changed-files.md +149 -0
  202. package/scripts/lib/docs/check-mdc-template-refs.md +222 -0
  203. package/scripts/lib/docs/check-reporter.md +175 -0
  204. package/scripts/lib/docs/discover-check-rules-from-cursor.md +157 -0
  205. package/scripts/lib/docs/discover-checkable-rules.md +165 -0
  206. package/scripts/lib/docs/ensure-tool.md +254 -0
  207. package/scripts/lib/docs/generated-markdown.md +275 -0
  208. package/scripts/lib/docs/gha-workflow.md +326 -0
  209. package/scripts/lib/docs/inline-template-links.md +303 -0
  210. package/scripts/lib/docs/list-rule-ids.md +156 -0
  211. package/scripts/lib/docs/load-cursor-config.md +147 -0
  212. package/scripts/lib/docs/mirror-parity.md +167 -0
  213. package/scripts/lib/worktree.mjs +26 -0
  214. package/scripts/worktree-cli.mjs +12 -2
  215. package/skills/coverage-fix/SKILL.md +34 -45
  216. package/skills/docgen/SKILL.md +44 -23
  217. package/skills/docgen/bench/etalon/firebase_hosting.md +19 -0
  218. package/skills/docgen/bench/etalon/k8s-tree.md +24 -0
  219. package/skills/docgen/bench/etalon/overlay-paths.md +24 -0
  220. package/skills/docgen/js/docgen-ignore.mjs +54 -0
  221. package/skills/docgen/js/docgen-scan.mjs +37 -21
  222. package/skills/llm-patch/SKILL.md +23 -2
  223. package/skills/start-check/SKILL.md +26 -53
  224. package/skills/start-check/js/check.mjs +211 -0
  225. package/skills/taze/SKILL.md +9 -3
  226. package/skills/taze/js/diff.mjs +154 -0
  227. package/types/bin/n-cursor.d.ts +1 -1
  228. package/skills/fix-tests/SKILL.md +0 -119
  229. package/skills/fix-tests/meta.json +0 -1
@@ -0,0 +1,128 @@
1
+ # `npm/rules/js-mssql/fix.mjs`
2
+
3
+ ## Огляд
4
+
5
+ Цей файл — точка входу правила `js-mssql` у бібліотеці правил пакета `@nitra/cursor`. Він має **дві ролі одночасно**:
6
+
7
+ 1. **Library mode** — експортує функцію `run(ctx)`, яку CLI-оркестратор (`bun n-cursor fix` / `bun n-cursor check`) імпортує разом з іншими правилами й послідовно викликає для одного спільного проходу по робочому дереву (з кешем `walkCache` тощо).
8
+ 2. **Standalone mode** — якщо файл запущено напряму (`bun rules/js-mssql/fix.mjs`), він самотужки виконує повний CLI-цикл правила (завантаження конфігу, whitelist, summary) — еквівалент `npx @nitra/cursor fix js-mssql`.
9
+
10
+ Сама логіка перевірки/виправлення у файлі **не реалізується** — це лише тонкий «launcher», який делегує роботу у спільний оркестратор `runStandardRule`. Завдяки цьому всі правила-«standard» (applies → JS-concerns → policy → mdc-refs) мають єдиний, передбачуваний і кешований pipeline.
11
+
12
+ Каталог правила `npm/rules/js-mssql/` містить:
13
+
14
+ - `fix.mjs` — цей файл (entry-point).
15
+ - `js-mssql.mdc` — людиночитна специфікація правила.
16
+ - `meta.json` — мета-інформація правила (id, version, тощо).
17
+ - `js/` — JS-concerns: фіксери/чекери, що працюють на рівні окремих JS/MJS/TS-файлів.
18
+ - `policy/` — policy-перевірки на рівні всього проєкту (зріз даних, агреговані інваріанти).
19
+ - `lib/` — допоміжні модулі правила.
20
+
21
+ ## Експорти / API
22
+
23
+ | Експорт | Тип | Призначення |
24
+ | ------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
25
+ | `run` | `function (ctx?) => Promise<number>` | Library-режим: одинична точка входу для зовнішнього оркестратора. Повертає exit-code правила (`0` — OK, `1` — порушення). |
26
+
27
+ Окрім експорту, файл має **top-level side-effect** під CLI-режимом — див. секцію «Потік виконання».
28
+
29
+ ### `run(ctx)`
30
+
31
+ ```js
32
+ export function run(ctx) {
33
+ return runStandardRule(import.meta.dirname, ctx)
34
+ }
35
+ ```
36
+
37
+ - **Сигнатура:** `run(ctx?: RuleContext): Promise<number>`
38
+ - **Параметри:**
39
+ - `ctx` _(optional)_ — об’єкт контексту прогону, який передає CLI-оркестратор. Тип імпортується JSDoc-посиланням з `../../scripts/lib/run-standard-rule.mjs` (`RuleContext`). Зазвичай несе спільні кешовані ресурси між правилами (наприклад, `walkCache` — кеш обходу файлів), щоб не повторювати дорогі IO-операції для кожного правила окремо.
40
+ - **Повертає:** `Promise<number>` — exit-code:
41
+ - `0` — порушень не знайдено;
42
+ - `1` — є порушення (правило фейлиться).
43
+ - **Side effects:** залежать від `runStandardRule`: читання файлів проєкту, потенційні автофікси на диску (якщо правило підтримує fix-mode), запис у summary-репорти, оновлення кешів у `ctx`.
44
+ - **Як визначається «корінь правила»:** через `import.meta.dirname` — повний шлях до директорії, де лежить цей `fix.mjs` (тобто `…/npm/rules/js-mssql/`). Саме цей шлях `runStandardRule` використовує, щоб знайти суміжні підтеки `js/`, `policy/`, файл `js-mssql.mdc` та `meta.json`.
45
+
46
+ ## Функції
47
+
48
+ ### `run(ctx)` — див. вище
49
+
50
+ Єдина функція, оголошена в цьому файлі. Жодних інших публічних чи приватних функцій модуль не містить — уся доменна логіка винесена у бібліотеку `scripts/lib/`.
51
+
52
+ ## Залежності
53
+
54
+ ### Внутрішні (відносні імпорти)
55
+
56
+ - `../../scripts/lib/run-rule-cli.mjs`
57
+ - `isRunAsCli(importMetaUrl): boolean` — детектує, чи запущено модуль як CLI-ентрі (а не імпортовано як бібліотеку). Порівнює `import.meta.url` поточного модуля з `process.argv[1]` (URL viewpoint).
58
+ - `runRuleCli(ruleDir): Promise<number>` — повний standalone-цикл одного правила: config-loading, whitelist, summary, повернення exit-коду.
59
+ - `../../scripts/lib/run-standard-rule.mjs`
60
+ - `runStandardRule(ruleDir, ctx?): Promise<number>` — узагальнений «standard» pipeline правила: `applies → JS-concerns → policy → mdc-refs`. Використовує `ctx` (наприклад, спільний `walkCache`), коли його передає зовнішній оркестратор.
61
+ - Експортує JSDoc-тип `RuleContext`, на який посилається анотація `run`.
62
+
63
+ ### Зовнішні (npm)
64
+
65
+ Прямих імпортів з npm у цьому файлі **немає**. Усі зовнішні залежності інкапсульовані в `scripts/lib/*`.
66
+
67
+ ### Платформенні / runtime
68
+
69
+ - **Bun ≥ 1.x** (або Node.js з підтримкою `import.meta.dirname`) — використовується `import.meta.dirname` та `import.meta.url`.
70
+ - **ESM** — файл написано як ES-модуль (`.mjs`), використовується `export` + top-level `await`.
71
+ - `process.exit` — глобал Node/Bun, явно лінт-проігноровано для CLI-сценарію.
72
+
73
+ ## Потік виконання / Використання
74
+
75
+ ### Library mode (типовий шлях у CI/IDE)
76
+
77
+ 1. CLI `bun n-cursor fix` (або `check`) сканує `npm/rules/*/fix.mjs`.
78
+ 2. Для кожного правила робить `import('…/fix.mjs')` і викликає `mod.run(ctx)` з підготовленим спільним контекстом.
79
+ 3. Для `js-mssql`: `run(ctx)` робить **один-рядковий** делегат у `runStandardRule(import.meta.dirname, ctx)`.
80
+ 4. `runStandardRule` усередині:
81
+ 1. Читає `meta.json` і `*.mdc` поруч із `fix.mjs`.
82
+ 2. Етап **applies** — визначає, чи правило взагалі застосовне до поточного дерева.
83
+ 3. Етап **JS-concerns** — викликає всі чекери/фіксери з `./js/`.
84
+ 4. Етап **policy** — викликає policy-перевірки з `./policy/` (агреговані інваріанти проєкту).
85
+ 5. Етап **mdc-refs** — звіряє наявні зв’язки/посилання у `.mdc`-документі.
86
+ 5. Повертає `0` / `1`, оркестратор зводить це у спільний звіт.
87
+
88
+ ### Standalone mode (точкова перевірка людиною)
89
+
90
+ 1. Розробник запускає файл напряму, наприклад:
91
+ ```bash
92
+ bun npm/rules/js-mssql/fix.mjs
93
+ ```
94
+ 2. Перевірка `isRunAsCli(import.meta.url)` повертає `true`.
95
+ 3. Виконується top-level `await runRuleCli(import.meta.dirname)`:
96
+ - Завантажує конфіг проєкту.
97
+ - Застосовує whitelist (які файли/директорії перевіряти).
98
+ - Викликає той самий стандартний pipeline (під капотом — `runStandardRule`).
99
+ - Друкує людиночитний summary.
100
+ 4. Результат передається в `process.exit(...)` — потрібний для IDE-інтеграції та CI-pipeline’ів, щоб non-zero exit-code сигналізував про порушення.
101
+
102
+ ### Чому окремо `run` і CLI-блок
103
+
104
+ Розділення на дві ролі дозволяє:
105
+
106
+ - **уникати дубльованого I/O** у бібліотечному режимі (один обхід дерева, кеш у `ctx`);
107
+ - **зберігати самодостатність** файлу для швидкого «прогнати правило одне, без всього іншого»;
108
+ - **тримати entry-point незмінним** для CLI-оркестратора — той знає лише, що у файлі є експорт `run`.
109
+
110
+ ### Лінт-винятки
111
+
112
+ Рядок `process.exit(await runRuleCli(import.meta.dirname))` має директивну «глушилку»:
113
+
114
+ - `n/no-process-exit` (eslint-plugin-n) — за замовчуванням забороняє `process.exit`.
115
+ - `unicorn/no-process-exit` (eslint-plugin-unicorn) — аналогічно.
116
+
117
+ Обидва правила свідомо відключені **лише** для standalone entry-point: CLI/IDE очікують exit-код для рішення «зелено/червоно».
118
+
119
+ ## Rebuild Test
120
+
121
+ З опису у цьому документі файл `fix.mjs` для правила `js-mssql` можна відтворити так:
122
+
123
+ 1. Створити ES-модуль `.mjs`.
124
+ 2. Імпортувати з `../../scripts/lib/run-rule-cli.mjs` дві іменовані функції: `isRunAsCli` та `runRuleCli`.
125
+ 3. Імпортувати з `../../scripts/lib/run-standard-rule.mjs` функцію `runStandardRule`.
126
+ 4. Оголосити іменований експорт `run(ctx)`, який повертає `runStandardRule(import.meta.dirname, ctx)`. JSDoc описує `ctx` як `RuleContext` (з того ж модуля) і повернення як `Promise<number>` (`0` — OK, `1` — порушення).
127
+ 5. Після експорту перевірити `isRunAsCli(import.meta.url)`; якщо `true` — виконати `process.exit(await runRuleCli(import.meta.dirname))`, попередньо вимкнувши коментарем правила `n/no-process-exit` та `unicorn/no-process-exit` для цього рядка (зі стислою причиною: standalone entry-point потребує exit-коду для CI/IDE).
128
+ 6. Не додавати жодних інших експортів і жодної доменної логіки — увесь pipeline `applies → JS-concerns → policy → mdc-refs` лишається в `runStandardRule`.
@@ -0,0 +1,263 @@
1
+ # deps.mjs — перевірка правила js-mssql.mdc
2
+
3
+ ## Огляд
4
+
5
+ Модуль `npm/rules/js-mssql/js/deps.mjs` — це автоматичний `check`-скрипт для правила `js-mssql.mdc`. Він виконує дві логічно різні перевірки на корені репозиторію:
6
+
7
+ 1. **Версійний аудит** усіх `package.json` (у тому числі workspace-пакетів): якщо в секції `dependencies` присутній пакет `mssql`, його semver-діапазон має давати ефективну версію не нижче `12.5.0`.
8
+ 2. **Статичний аналіз вихідного коду** (JS/TS) на безпечне використання драйвера `mssql`:
9
+ - заборона створення `new sql.ConnectionPool(...)` всередині функцій (пул має бути singleton на рівні модуля);
10
+ - заборона спільного (shared) `Request`, наприклад `export const request = pool.request()`;
11
+ - заборона викликів `query(\`...\`)`як звичайної функції — потрібен tagged template`query\`...\``;
12
+ - заборона динамічних SQL-списків через `.join(',')` у конструкціях `IN (...)` / `VALUES (...)` (треба TVP, `sql.Table`);
13
+ - вимога числового парсингу значень у `IN (${...})` (`parseInt` / `Number` / `BigInt` / `parseFloat` + фільтр від `NaN`);
14
+ - вимога винести значення для `IN (${...})` в окрему змінну і додати guard на пустоту з `throw`.
15
+
16
+ Скрипт використовує спільну інфраструктуру репорту (`createCheckReporter`) і повертає числовий exit code, придатний для CI. Усі повідомлення префіксовані `js-mssql:` для зручної фільтрації.
17
+
18
+ Файл є ESM-модулем (`.mjs`), без top-level side effects: експортується лише асинхронна функція `check()`, яка ініціює виконання.
19
+
20
+ ## Експорти / API
21
+
22
+ | Символ | Тип | Призначення |
23
+ | ------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
24
+ | `check` | `async function(): Promise<number>` | Єдиний публічний експорт. Виконує повну перевірку правила `js-mssql.mdc` у поточному `process.cwd()` і повертає `0` (OK) або `1` (є порушення). |
25
+
26
+ Інші функції в модулі (`findAllSourcePathsForMssqlScan`, `asObject`, `getMssqlDependencyRange`, `parseLeadingSemver`, `semverGte`, `auditMssqlVersionInPackageJson`, `aggregateMssqlVersionsAcrossPackages`, `scanMssqlOneSourceFile`, `reportZeroMssqlSourceViolations`, `auditMssqlSources`) є **внутрішніми** — не експортуються і призначені лише для декомпозиції логіки `check()`.
27
+
28
+ ### Константи
29
+
30
+ | Константа | Значення | Опис |
31
+ | ------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------ |
32
+ | `VERSION_PREFIX_RE` | `/^[\^~>=<]+\s*/u` | Регулярка для відрізання префіксів semver-діапазону (`^`, `~`, `>`, `=`, `<` та комбінацій) перед парсингом. |
33
+ | `SEMVER_RE` | `/^(\d+)\.(\d+)\.(\d+)/u` | Регулярка для захоплення першої semver-трійки `major.minor.patch` після очищення префіксу. |
34
+ | `MIN_MSSQL_VERSION` | `{ major: 12, minor: 5, patch: 0 }` | Мінімально дозволена версія `mssql`, як її задає правило `js-mssql.mdc`. |
35
+
36
+ ## Функції
37
+
38
+ ### `findAllSourcePathsForMssqlScan(repoRoot, ignorePaths)`
39
+
40
+ Внутрішня. Збирає абсолютні шляхи всіх JS/TS-файлів-кандидатів для скану `mssql`.
41
+
42
+ - **Сигнатура:** `async function findAllSourcePathsForMssqlScan(repoRoot: string, ignorePaths: string[]): Promise<string[]>`
43
+ - **Параметри:**
44
+ - `repoRoot` — абсолютний шлях до кореня репозиторію;
45
+ - `ignorePaths` — масив абсолютних шляхів каталогів, які повністю виключаються з обходу (зчитується з `.cursorignore`).
46
+ - **Повертає:** масив абсолютних шляхів файлів, відсортований за відносним шляхом (`localeCompare`), щоб порядок звітів був детермінованим.
47
+ - **Side effects:** читає файлову систему через `walkDir`; нормалізує windows-роздільники `\` у POSIX `/` перед перевіркою `isMssqlScanSourceFile`.
48
+
49
+ ### `asObject(v)`
50
+
51
+ Внутрішня. Безпечне приведення невідомого значення до plain-object.
52
+
53
+ - **Сигнатура:** `function asObject(v: unknown): Record<string, unknown>`
54
+ - **Логіка:** повертає `{}`, якщо `v` falsy, не `object`, або масив; інакше повертає сам `v` як `Record<string, unknown>` (через JSDoc-cast).
55
+ - **Side effects:** немає.
56
+
57
+ ### `getMssqlDependencyRange(deps)`
58
+
59
+ Внутрішня. Витягає рядок версії `dependencies.mssql`.
60
+
61
+ - **Сигнатура:** `function getMssqlDependencyRange(deps: unknown): string | null`
62
+ - **Параметри:** `deps` — значення поля `dependencies` з `package.json` (може бути будь-чим).
63
+ - **Повертає:** триманий (`trim`) рядок версії, або `null`, якщо ключ відсутній / значення не є непорожнім рядком.
64
+ - **Side effects:** немає.
65
+
66
+ ### `parseLeadingSemver(range)`
67
+
68
+ Внутрішня. Парсить першу semver-трійку з діапазону виду `"^12.5.0"`, `">=12.5.0"`, `"12.5.0"`.
69
+
70
+ - **Сигнатура:** `function parseLeadingSemver(range: string): { major: number, minor: number, patch: number } | null`
71
+ - **Параметри:** `range` — версійний діапазон у синтаксисі npm.
72
+ - **Повертає:** об'єкт `{ major, minor, patch }` або `null`, якщо не вдалось розпарсити (або будь-який компонент — `NaN`).
73
+ - **Алгоритм:**
74
+ 1. `String(range).trim()` → видалення префіксів через `VERSION_PREFIX_RE`;
75
+ 2. `match(SEMVER_RE)` → захоплення трьох чисел;
76
+ 3. конвертація через `Number`, перевірка `Number.isNaN`.
77
+ - **Side effects:** немає.
78
+
79
+ ### `semverGte(a, b)`
80
+
81
+ Внутрішня. Порівняння semver "більше або дорівнює".
82
+
83
+ - **Сигнатура:** `function semverGte(a: SemverObj, b: SemverObj): boolean`
84
+ - **Параметри:** обидві трійки `{ major, minor, patch }`.
85
+ - **Повертає:** `true`, якщо `a >= b` за лексикографічним порядком `(major, minor, patch)`.
86
+ - **Side effects:** немає.
87
+
88
+ ### `auditMssqlVersionInPackageJson(rel, parsed, pass, fail)`
89
+
90
+ Внутрішня. Аудит одного `package.json` на `dependencies.mssql`.
91
+
92
+ - **Сигнатура:** `function auditMssqlVersionInPackageJson(rel: string, parsed: unknown, pass: (msg: string) => void, fail: (msg: string) => void): { found: 0 | 1, bad: 0 | 1 }`
93
+ - **Параметри:**
94
+ - `rel` — людино-читабельний шлях (відносний, з `/` як роздільник);
95
+ - `parsed` — розпарсений JSON `package.json`;
96
+ - `pass`, `fail` — колбеки звіту з `createCheckReporter`.
97
+ - **Повертає:** інкремент лічильників:
98
+ - `found` — `1`, якщо в `dependencies` знайдено ключ `mssql`, інакше `0`;
99
+ - `bad` — `1`, якщо знайдено, але версія нечитабельна або менша за `MIN_MSSQL_VERSION`.
100
+ - **Side effects:** виклики `pass(...)` / `fail(...)` з конкретними повідомленнями (формат `js-mssql: <rel>: ... (js-mssql.mdc)`).
101
+
102
+ ### `aggregateMssqlVersionsAcrossPackages(repoRoot, pkgJsonPaths, pass, fail)`
103
+
104
+ Внутрішня. Прогін усіх `package.json` із підсумками.
105
+
106
+ - **Сигнатура:** `async function aggregateMssqlVersionsAcrossPackages(repoRoot: string, pkgJsonPaths: string[], pass: (msg: string) => void, fail: (msg: string) => void): Promise<{ found: number, bad: number }>`
107
+ - **Параметри:**
108
+ - `repoRoot` — корінь репозиторію;
109
+ - `pkgJsonPaths` — абсолютні шляхи до всіх знайдених `package.json`.
110
+ - **Повертає:** сукупні лічильники `{ found, bad }` по всіх файлах.
111
+ - **Side effects:**
112
+ - читає кожен `package.json` через `readFile`;
113
+ - якщо файл — невалідний JSON, викликає `fail('js-mssql: <rel> — невалідний JSON')` і пропускає його (`continue`);
114
+ - акумулює інкременти з `auditMssqlVersionInPackageJson`.
115
+
116
+ ### `scanMssqlOneSourceFile(rel, content, counters, fail)`
117
+
118
+ Внутрішня. Прогін **одного** JS/TS-файлу через шість сканерів з `../lib/mssql-pool-scan.mjs`.
119
+
120
+ - **Сигнатура:** `function scanMssqlOneSourceFile(rel: string, content: string, counters: Record<string, number>, fail: (msg: string) => void): void`
121
+ - **Параметри:**
122
+ - `rel` — relative-шлях файлу (для повідомлень);
123
+ - `content` — повний вихідний код файлу;
124
+ - `counters` — мутабельний агрегатор лічильників (див. нижче);
125
+ - `fail` — колбек звіту про порушення.
126
+ - **Лічильники в `counters` (інкрементуються по одному за порушення):**
127
+ - `violations` — `new sql.ConnectionPool(...)` всередині функції;
128
+ - `sharedRequestViolations` — shared `Request` (наприклад `export const request = pool.request()`);
129
+ - `unsafeQueryCalls` — `query(\`...\`)` як виклик функції замість tagged template;
130
+ - `unsafeDynamicSqlLists` — динамічні SQL-списки через `.join(',')` у `IN/VALUES`;
131
+ - `unparsedInLists` — `IN (${...})` без числового парсера значень;
132
+ - `inListGuardViolations` — відсутній або неправильно розташований guard на пустоту IN-списку (розгалуження за `v.reason === 'missing_guard'` дає різні тексти повідомлень).
133
+ - **Side effects:** виклики `fail(...)` з конкретним `:line` та `snippet` для кожного знайденого порушення; мутує `counters`.
134
+
135
+ ### `reportZeroMssqlSourceViolations(counters, pass)`
136
+
137
+ Внутрішня. Для кожного лічильника, що залишився `0`, дає один `pass`-рядок.
138
+
139
+ - **Сигнатура:** `function reportZeroMssqlSourceViolations(counters: Record<string, number>, pass: (msg: string) => void): void`
140
+ - **Семантика:** перетворює "відсутність порушень" на явні позитивні рядки звіту — щоб у вихідному логу було видно, які саме інваріанти виконано (а не лише сумарний `OK`).
141
+ - **Side effects:** виклики `pass(...)` (від 0 до 6, залежно від лічильників).
142
+
143
+ ### `auditMssqlSources(repoRoot, ignorePaths, pass, fail)`
144
+
145
+ Внутрішня. Повний аудит усіх JS/TS-джерел репо щодо безпечного використання `mssql`.
146
+
147
+ - **Сигнатура:** `async function auditMssqlSources(repoRoot: string, ignorePaths: string[], pass: (msg: string) => void, fail: (msg: string) => void): Promise<void>`
148
+ - **Алгоритм:**
149
+ 1. збирає список файлів через `findAllSourcePathsForMssqlScan`;
150
+ 2. якщо файлів немає — один `pass`-рядок `'js-mssql: немає JS/TS файлів для скану singleton ConnectionPool'` і `return`;
151
+ 3. ініціалізує `counters` нулями (`violations`, `sharedRequestViolations`, `unsafeQueryCalls`, `unsafeDynamicSqlLists`, `unparsedInLists`, `inListGuardViolations`);
152
+ 4. послідовно читає кожен файл через `readFile(absPath, 'utf8')`, нормалізує `rel` і викликає `scanMssqlOneSourceFile`;
153
+ 5. в кінці викликає `reportZeroMssqlSourceViolations(counters, pass)`.
154
+ - **Side effects:** I/O (читання файлів); виклики `pass` / `fail`.
155
+
156
+ ### `check()` _(export)_
157
+
158
+ Публічна. Виконує повну перевірку правила.
159
+
160
+ - **Сигнатура:** `export async function check(): Promise<number>`
161
+ - **Параметри:** немає (працює відносно `process.cwd()`).
162
+ - **Повертає:** `number` — exit code від `reporter.getExitCode()` (`0` — OK, `1` — є проблеми).
163
+ - **Алгоритм:**
164
+ 1. створює репортер: `createCheckReporter()` → деструктурує `{ pass, fail }`;
165
+ 2. `repoRoot = process.cwd()`;
166
+ 3. **early-return**: якщо в корені немає `package.json` (`existsSync`), записує `pass('js-mssql: package.json у корені відсутній — перевірку пропущено')` і повертає поточний exit code;
167
+ 4. зчитує `ignorePaths` через `loadCursorIgnorePaths(repoRoot)`;
168
+ 5. збирає всі `package.json` у репозиторії через `findAllPackageJsonPaths(repoRoot, ignorePaths)`;
169
+ 6. **early-return**: якщо `package.json` не знайдено зовсім — `pass('js-mssql: package.json не знайдено — перевірку пропущено')` + повернення exit code;
170
+ 7. виконує `aggregateMssqlVersionsAcrossPackages(...)` → `{ found, bad }`;
171
+ 8. **early-return**: якщо `found === 0`, `pass('js-mssql: пакет mssql не знайдено в dependencies жодного package.json')` + повернення exit code (статичний аналіз не запускається, бо `mssql` у проєкті не використовується);
172
+ 9. якщо `bad === 0` — `pass('js-mssql: всі знайдені dependencies.mssql відповідають мінімальній версії 12.5.0 (<found>)')`;
173
+ 10. виконує `auditMssqlSources(repoRoot, ignorePaths, pass, fail)`;
174
+ 11. повертає `reporter.getExitCode()`.
175
+ - **Side effects:** I/O (читання FS), звітування через `pass`/`fail` репортера.
176
+
177
+ ## Залежності
178
+
179
+ ### Стандартні модулі Node.js
180
+
181
+ | Імпорт | Звідки | Використання |
182
+ | ------------------ | ------------------ | ---------------------------------------------------------------------------------- |
183
+ | `existsSync` | `node:fs` | Перевірка наявності `package.json` у корені (швидкий синхронний guard). |
184
+ | `readFile` | `node:fs/promises` | Асинхронне читання `package.json` та джерельних файлів у UTF-8. |
185
+ | `join`, `relative` | `node:path` | Побудова шляху до `package.json` та нормалізація відносних шляхів для повідомлень. |
186
+
187
+ ### Внутрішні модулі репозиторію
188
+
189
+ | Імпорт | Звідки | Призначення |
190
+ | ---------------------------------------------- | ---------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
191
+ | `createCheckReporter` | `../../../scripts/lib/check-reporter.mjs` | Уніфікований репортер для всіх `check`-скриптів: накопичує `pass`/`fail` рядки і формує exit code. |
192
+ | `findAllPackageJsonPaths` | `../../../scripts/utils/find-package-json-paths.mjs` | Рекурсивний пошук усіх `package.json` (моно-репо/workspaces) з урахуванням ignore-шляхів. |
193
+ | `findMssqlPerRequestConnectionInText` | `../lib/mssql-pool-scan.mjs` | Пошук `new sql.ConnectionPool(...)` всередині функцій. |
194
+ | `findSharedMssqlRequestInText` | `../lib/mssql-pool-scan.mjs` | Пошук shared `Request` (наприклад `export const request = pool.request()`). |
195
+ | `findUnsafeMssqlQueryTemplateCallInText` | `../lib/mssql-pool-scan.mjs` | Пошук `query(\`...\`)` як звичайного виклику замість tagged template. |
196
+ | `findUnsafeMssqlDynamicSqlListInText` | `../lib/mssql-pool-scan.mjs` | Пошук динамічних SQL-списків через `.join(',')` у `IN/VALUES`. |
197
+ | `findUnsafeMssqlInListUnparsedInText` | `../lib/mssql-pool-scan.mjs` | Пошук `IN (${...})` без числового парсингу значень. |
198
+ | `findUnsafeMssqlInListMissingEmptyGuardInText` | `../lib/mssql-pool-scan.mjs` | Пошук IN-списків без guard'у на пустоту з `throw`. |
199
+ | `isMssqlScanSourceFile` | `../lib/mssql-pool-scan.mjs` | Фільтр-предикат: чи треба сканувати файл за його relative-шляхом. |
200
+ | `loadCursorIgnorePaths` | `../../../scripts/lib/load-cursor-config.mjs` | Завантаження `.cursorignore` → масив абсолютних ignore-шляхів. |
201
+ | `walkDir` | `../../../scripts/utils/walkDir.mjs` | Рекурсивний обхід файлової системи з callback на кожен файл і ignore-каталогами. |
202
+
203
+ ### Очікувана форма колбеків репортера
204
+
205
+ ```js
206
+ const reporter = createCheckReporter()
207
+ // reporter: { pass(msg: string): void, fail(msg: string): void, getExitCode(): number }
208
+ ```
209
+
210
+ `pass` додає позитивне повідомлення (не впливає на exit code), `fail` — фіксує порушення і змушує `getExitCode()` повернути `1`.
211
+
212
+ ## Потік виконання / Використання
213
+
214
+ ### Сценарій інтеграції
215
+
216
+ Модуль є частиною інфраструктури `n-cursor` правил `npm/rules/js-mssql/`. Він викликається універсальним runner'ом правил (наприклад через `bun run` або `n-cursor` CLI), який імпортує `check` і використовує її exit code як підсумок.
217
+
218
+ Типове використання:
219
+
220
+ ```js
221
+ import { check } from './deps.mjs'
222
+
223
+ const exitCode = await check()
224
+ process.exit(exitCode)
225
+ ```
226
+
227
+ ### Послідовність дій усередині `check()`
228
+
229
+ 1. **Ініціалізація репортера.** Створюється локальний `reporter` через `createCheckReporter()`.
230
+ 2. **Guard 1 — кореневий `package.json`.** Якщо в `process.cwd()` немає `package.json`, перевірка вважається непридатною; виставляється `pass` і повертається exit code (зазвичай `0`).
231
+ 3. **Завантаження ignore-шляхів.** Зчитуються через `loadCursorIgnorePaths(repoRoot)`.
232
+ 4. **Збір усіх `package.json`.** `findAllPackageJsonPaths(repoRoot, ignorePaths)` повертає масив абсолютних шляхів усіх `package.json` репозиторію (з урахуванням workspace-пакетів і ignore).
233
+ 5. **Guard 2 — порожній список.** Якщо `package.json` зовсім немає — пропуск перевірки з відповідним `pass`.
234
+ 6. **Версійний аудит.** `aggregateMssqlVersionsAcrossPackages` обходить кожен `package.json`, парсить JSON, для кожного знайденого `dependencies.mssql` запускає `auditMssqlVersionInPackageJson`. Підсумок — `{ found, bad }`.
235
+ 7. **Guard 3 — `mssql` не використовується.** Якщо `found === 0`, фіксується позитивний рядок `'js-mssql: пакет mssql не знайдено в dependencies жодного package.json'` і виконання завершується — статичний аналіз джерел **не запускається** (немає сенсу шукати порушення для пакета, якого немає в залежностях).
236
+ 8. **Підсумковий pass про версії.** Якщо `bad === 0` (всі версії OK), додається підсумковий `pass` з кількістю знайдених.
237
+ 9. **Аудит джерел.** `auditMssqlSources` сканує всі JS/TS-файли (через `walkDir` + `isMssqlScanSourceFile`), застосовує шість сканерів безпеки і фіксує кожне порушення через `fail`. Відсутність порушень за кожним типом конвертується у явний `pass` через `reportZeroMssqlSourceViolations`.
238
+ 10. **Повернення exit code.** `reporter.getExitCode()` → `0` якщо жодного `fail` не було, інакше `1`.
239
+
240
+ ### Формати повідомлень
241
+
242
+ Усі повідомлення мають префікс `js-mssql:` і додатково цитують правило `js-mssql.mdc` у негативних випадках. Приклади:
243
+
244
+ - **Версія OK:** `js-mssql: package.json: dependencies.mssql "^12.5.0" (>=12.5.0)`
245
+ - **Версія нижче мінімуму:** `js-mssql: package.json: dependencies.mssql "^11.0.0" — має бути >=12.5.0 (js-mssql.mdc)`
246
+ - **Невалідний JSON:** `js-mssql: package.json — невалідний JSON`
247
+ - **Per-request pool:** `js-mssql: src/db.js:42 — не створюй new sql.ConnectionPool(...) на кожен запит; використовуй singleton sql.ConnectionPool: <snippet>`
248
+ - **Відсутній guard для IN:** `js-mssql: src/db.js:58 — перед IN-списком "ids" потрібна перевірка на пустоту з throw (наприклад if (!ids.length) throw ...), інакше можливі некоректні запити (js-mssql.mdc): <snippet>`
249
+
250
+ ### Платформо-незалежна нормалізація шляхів
251
+
252
+ У всіх місцях, де формується `rel`, послідовно застосовується `relative(repoRoot, absPath).split('\\').join('/')`. Це робить повідомлення стабільними на Windows і POSIX одночасно й узгодженими з шаблонами `isMssqlScanSourceFile`.
253
+
254
+ ### Корнер-кейси
255
+
256
+ - **Відсутній `package.json` у корені** — перевірка повністю пропускається з позитивним `pass`.
257
+ - **Жодного `package.json`** (наприклад, у нестандартному репо без npm) — перевірка пропускається.
258
+ - **`dependencies` відсутній або не object** — `getMssqlDependencyRange` повертає `null` через `asObject`, лічильник не збільшується.
259
+ - **Нечитабельна версія** (наприклад `"latest"`, `"workspace:*"`, `"git+..."` без чистого `MAJOR.MINOR.PATCH`) — `parseLeadingSemver` повертає `null`, фіксується `fail` "має нечитабельну версію".
260
+ - **Версія дорівнює мінімуму** — `semverGte(parsedVer, MIN_MSSQL_VERSION)` дає `true`, фіксується `pass`.
261
+ - **`mssql` відсутній у всіх `package.json`** — статичний аналіз не запускається (оптимізація для проєктів, які не використовують MSSQL).
262
+ - **Файл — невалідний JSON** — фіксується `fail`, обхід продовжується (`continue`).
263
+ - **Жодного JS/TS-файлу** у репо для скану — фіксується позитивний `pass`, виконання продовжується нормально.