@nitra/cursor 5.3.3 → 5.4.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 (157) hide show
  1. package/.claude-template/settings.template.json +2 -2
  2. package/.pi-template/extensions/n-cursor-adr/docs/index.md +13 -24
  3. package/CHANGELOG.md +17 -0
  4. package/bin/n-cursor.js +43 -22
  5. package/lib/docs/llm.md +23 -12
  6. package/lib/docs/models.md +29 -18
  7. package/lib/docs/omlx-trace.md +51 -0
  8. package/lib/docs/omlx.md +31 -15
  9. package/lib/omlx.mjs +2 -5
  10. package/package.json +1 -1
  11. package/rules/abie/docs/fix.md +17 -11
  12. package/rules/adr/docs/fix.md +25 -140
  13. package/rules/bun/docs/fix.md +18 -151
  14. package/rules/capacitor/docs/fix.md +16 -13
  15. package/rules/capacitor/js/docs/platforms.md +31 -43
  16. package/rules/changelog/docs/fix.md +25 -169
  17. package/rules/ci4/docs/fix.md +11 -14
  18. package/rules/doc-files/doc-files.mdc +60 -0
  19. package/rules/doc-files/docs/fix.md +31 -0
  20. package/rules/doc-files/fix.mjs +19 -0
  21. package/{skills → rules}/doc-files/js/docgen-extract.mjs +42 -19
  22. package/{skills → rules}/doc-files/js/docgen-ignore.mjs +2 -1
  23. package/{skills → rules}/doc-files/js/docgen-scan.mjs +9 -1
  24. package/{skills → rules}/doc-files/js/docs/docgen-crc.md +1 -1
  25. package/rules/doc-files/js/docs/docgen-extract-anchors.md +45 -0
  26. package/rules/doc-files/js/docs/docgen-extract.md +39 -0
  27. package/rules/doc-files/js/docs/docgen-files-batch.md +35 -0
  28. package/rules/doc-files/js/docs/docgen-gen.md +46 -0
  29. package/rules/doc-files/js/docs/docgen-ignore.md +37 -0
  30. package/rules/doc-files/js/docs/docgen-prompts.md +39 -0
  31. package/rules/doc-files/js/docs/docgen-scan.md +54 -0
  32. package/rules/doc-files/js/docs/lint.md +36 -0
  33. package/rules/doc-files/js/docs/units-js.md +31 -0
  34. package/rules/doc-files/js/docs/units-rs.md +35 -0
  35. package/rules/doc-files/js/docs/units.md +30 -0
  36. package/rules/doc-files/js/lint.mjs +96 -0
  37. package/{skills → rules}/doc-files/js/units-rs.mjs +37 -17
  38. package/rules/doc-files/lint/docs/lint.md +37 -0
  39. package/rules/doc-files/lint/lint.mjs +105 -0
  40. package/rules/doc-files/meta.json +1 -0
  41. package/rules/docker/docs/fix.md +21 -161
  42. package/rules/efes/docs/fix.md +23 -194
  43. package/rules/feedback/docs/fix.md +10 -8
  44. package/rules/ga/docs/fix.md +10 -5
  45. package/rules/graphql/docs/fix.md +23 -119
  46. package/rules/hasura/docs/fix.md +19 -5
  47. package/rules/hasura/js/docs/internal_urls.md +34 -307
  48. package/rules/image-avif/docs/fix.md +16 -127
  49. package/rules/image-compress/docs/fix.md +20 -141
  50. package/rules/image-compress/js/docs/package_setup.md +22 -182
  51. package/rules/js-bun-db/docs/fix.md +23 -139
  52. package/rules/js-bun-db/js/docs/safety.md +33 -221
  53. package/rules/js-bun-redis/docs/fix.md +25 -114
  54. package/rules/js-bun-redis/js/docs/imports.md +18 -166
  55. package/rules/js-lint/docs/fix.md +30 -108
  56. package/rules/js-lint/js/docs/lint-findings.md +37 -17
  57. package/rules/js-lint/js/docs/lint.md +22 -238
  58. package/rules/js-lint/js/docs/tooling.md +34 -331
  59. package/rules/js-lint-ci/docs/fix.md +16 -149
  60. package/rules/js-lint-ci/js/docs/lint.md +16 -136
  61. package/rules/js-mssql/docs/fix.md +18 -123
  62. package/rules/js-mssql/js/docs/deps.md +28 -251
  63. package/rules/js-run/docs/fix.md +23 -138
  64. package/rules/js-run/js/docs/runtime.md +24 -378
  65. package/rules/k8s/docs/fix.md +18 -123
  66. package/rules/nginx-default-tpl/docs/fix.md +22 -118
  67. package/rules/nginx-default-tpl/js/docs/template.md +38 -360
  68. package/rules/npm-module/docs/fix.md +27 -89
  69. package/rules/npm-module/js/docs/header_doc_pointer.md +15 -15
  70. package/rules/npm-module/js/docs/package_structure.md +36 -258
  71. package/rules/npm-module/js/docs/rule_meta.md +25 -127
  72. package/rules/npm-module/js/docs/skill_meta.md +18 -180
  73. package/rules/php/docs/fix.md +21 -98
  74. package/rules/php/js/docs/tooling.md +20 -143
  75. package/rules/python/docs/fix.md +25 -157
  76. package/rules/python/js/docs/applies.md +20 -98
  77. package/rules/python/js/docs/tooling.md +27 -144
  78. package/rules/rego/docs/fix.md +24 -112
  79. package/rules/rego/js/docs/applies.md +20 -164
  80. package/rules/rego/js/docs/lint.md +15 -110
  81. package/rules/release/docs/fix.md +16 -114
  82. package/rules/rust/docs/fix.md +24 -119
  83. package/rules/rust/js/docs/applies.md +20 -129
  84. package/rules/security/docs/fix.md +21 -78
  85. package/rules/security/js/docs/sample_secret.md +23 -182
  86. package/rules/security/js/docs/trufflehog.md +19 -128
  87. package/rules/style-lint/docs/fix.md +16 -150
  88. package/rules/style-lint/js/docs/lint.md +21 -172
  89. package/rules/style-lint/js/docs/tooling.md +19 -184
  90. package/rules/tauri/docs/fix.md +26 -152
  91. package/rules/tauri/js/docs/cargo_mutants_config.md +21 -159
  92. package/rules/tauri/js/docs/tooling.md +20 -217
  93. package/rules/test/docs/fix.md +19 -127
  94. package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +15 -127
  95. package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +17 -153
  96. package/rules/test/js/docs/cargo_mutants_config.md +24 -164
  97. package/rules/test/js/docs/location.md +24 -126
  98. package/rules/test/js/docs/no-process-chdir.md +20 -151
  99. package/rules/test/js/docs/no-relative-fs-path.md +24 -261
  100. package/rules/test/js/docs/stryker_config.md +48 -148
  101. package/rules/test/js/docs/vitest-config-pool-forks.md +21 -164
  102. package/rules/text/docs/fix.md +25 -113
  103. package/rules/text/js/docs/forbidden-prettier.md +21 -132
  104. package/rules/text/js/docs/formatting.md +60 -251
  105. package/rules/text/js/docs/lint.md +17 -114
  106. package/rules/vue/docs/fix.md +25 -118
  107. package/rules/vue/js/docs/packages.md +25 -323
  108. package/rules/worktree/docs/fix.md +31 -150
  109. package/scripts/coverage-classify/docs/index.md +23 -209
  110. package/scripts/coverage-classify/docs/verdict-schema.md +14 -159
  111. package/scripts/dispatcher/docs/trace.md +35 -0
  112. package/scripts/docs/auto-rules.md +37 -361
  113. package/scripts/docs/lint-cli.md +12 -13
  114. package/scripts/docs/post-tool-use-fix.md +16 -15
  115. package/scripts/docs/skills-cli.md +26 -23
  116. package/scripts/docs/sync-claude-config.md +94 -34
  117. package/scripts/docs/worktree-cli.md +11 -34
  118. package/scripts/lib/docs/assert-project-root.md +14 -16
  119. package/scripts/lib/docs/changed-files.md +24 -139
  120. package/scripts/lib/docs/discover-check-rules-from-cursor.md +14 -146
  121. package/scripts/lib/docs/rule-predicates.md +20 -17
  122. package/scripts/lib/docs/run-rule-cli.md +14 -18
  123. package/scripts/lib/docs/run-rule.md +13 -20
  124. package/scripts/lib/docs/run-standard-rule.md +12 -15
  125. package/scripts/lib/docs/sync-gitignore-worktree.md +15 -18
  126. package/scripts/lib/rule-predicates.mjs +1 -1
  127. package/scripts/sync-claude-config.mjs +4 -1
  128. package/scripts/utils/docs/with-lock.md +19 -12
  129. package/scripts/utils/with-lock.mjs +4 -2
  130. package/skills/doc-aggregate/SKILL.md +2 -2
  131. package/skills/doc-aggregate/js/docgen-ignore.mjs +6 -6
  132. package/skills/doc-aggregate/js/docs/docgen-ignore.md +1 -1
  133. package/skills/doc-aggregate/js/docs/docgen-scan.md +78 -0
  134. package/skills/doc-files/.changes/260612-0012.md +5 -0
  135. package/skills/doc-files/.changes/260612-0031.md +5 -0
  136. package/skills/doc-files/.changes/260612-0036.md +5 -0
  137. package/skills/doc-files/.changes/260612-0114.md +5 -0
  138. package/skills/doc-files/SKILL.md +6 -6
  139. package/skills/fix/js/docs/llm-worker.md +17 -15
  140. package/skills/fix/js/docs/orchestrator.md +30 -23
  141. package/skills/fix/js/docs/t0.md +26 -16
  142. package/skills/start-check/js/docs/check.md +26 -22
  143. package/skills/taze/js/docs/diff.md +44 -20
  144. package/skills/doc-files/js/docs/docgen-extract-anchors.md +0 -27
  145. package/skills/doc-files/js/docs/docgen-extract.md +0 -29
  146. package/skills/doc-files/js/docs/docgen-files-batch.md +0 -25
  147. package/skills/doc-files/js/docs/docgen-gen.md +0 -30
  148. package/skills/doc-files/js/docs/docgen-prompts.md +0 -32
  149. package/skills/doc-files/js/docs/docgen-scan.md +0 -25
  150. package/skills/doc-files/js/docs/units-rs.md +0 -35
  151. /package/{skills → rules}/doc-files/js/docgen-crc.mjs +0 -0
  152. /package/{skills → rules}/doc-files/js/docgen-extract-anchors.mjs +0 -0
  153. /package/{skills → rules}/doc-files/js/docgen-files-batch.mjs +0 -0
  154. /package/{skills → rules}/doc-files/js/docgen-gen.mjs +0 -0
  155. /package/{skills → rules}/doc-files/js/docgen-prompts.mjs +0 -0
  156. /package/{skills → rules}/doc-files/js/units-js.mjs +0 -0
  157. /package/{skills → rules}/doc-files/js/units.mjs +0 -0
@@ -1,148 +1,32 @@
1
- # `fix.mjs` — entry-point правила `js-bun-db`
1
+ ---
2
+ docgen:
3
+ source: npm/rules/js-bun-db/fix.mjs
4
+ crc: 38cf876b
5
+ score: 100
6
+ ---
2
7
 
3
- ## Огляд
4
-
5
- Файл `npm/rules/js-bun-db/fix.mjs` — це **точка входу** (entry-point) для правила `js-bun-db` пакета `@nitra/cursor`. Правило перевіряє/виправляє код, що працює з базою даних у середовищі Bun (JavaScript runtime), і виконується у стандартному CI4-пайплайні:
6
-
7
- 1. `applies` — визначає, до яких файлів застосовується правило;
8
- 2. `JS-concerns` — перевіряє/чинить специфічні JS-аспекти (через стандартний пайплайн);
9
- 3. `policy` — застосовує політики правила (наприклад, заборонені патерни, переписування коду);
10
- 4. `mdc-refs` — оновлює перехресні посилання у `.mdc`-документах (Markdown Cursor).
11
-
12
- Файл виконує **дві ролі одночасно**:
13
-
14
- - **Library mode** — експортує функцію `run(ctx)`, яку викликає зовнішній orchestrator (CLI `@nitra/cursor`, ESLint-обгортка, інші правила) для виконання пайплайну у спільному процесі (з можливістю переюзу `walkCache` через переданий `ctx`).
15
- - **Standalone mode** — якщо файл запущено напряму як CLI (`bun rules/js-bun-db/fix.mjs`), він проганяє повний CLI-цикл (`runRuleCli`) із завантаженням конфігурації, whitelist-фільтрацією та підсумковим виводом, після чого виставляє відповідний `process.exit(code)` для CI/IDE.
16
-
17
- Файл свідомо мінімалістичний: уся реальна логіка винесена у бібліотечні утиліти (`run-standard-rule.mjs`, `run-rule-cli.mjs`); `fix.mjs` лише делегує виклики, передаючи `import.meta.dirname` як ідентифікатор поточної директорії правила.
18
-
19
- ## Експорти / API
20
-
21
- | Експорт | Тип | Призначення |
22
- | ------- | ---------- | ---------------------------------------------------------------------------------------- |
23
- | `run` | `function` | Library-режим: виконує стандартний пайплайн правила для переданого/дефолтного контексту. |
24
-
25
- Інших іменованих експортів немає. Файл також містить **side-effect-блок** верхнього рівня (див. секцію [Потік виконання](#потік-виконання--використання)), який спрацьовує лише за умови запуску модуля як CLI.
26
-
27
- ## Функції
28
-
29
- ### `run(ctx)`
30
-
31
- ```js
32
- export function run(ctx)
33
- ```
34
-
35
- **Призначення.** Запускає стандартний пайплайн правила (`applies → JS-concerns → policy → mdc-refs`) для директорії, у якій лежить сам `fix.mjs`. Тобто — для правила `js-bun-db`. Делегує всю роботу функції `runStandardRule`.
36
-
37
- **Параметри.**
38
-
39
- | Ім'я | Тип | Обов'язковість | Опис |
40
- | ----- | ----------------------------------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
41
- | `ctx` | `RuleContext` (з `../../scripts/lib/run-standard-rule.mjs`) | Опціональний | Контекст прогону (наприклад, `walkCache` — закешований обхід файлової системи, поділюваний між правилами одного CLI-сеансу). Якщо не передано — `runStandardRule` створює свій. |
42
-
43
- **Повертає.** `Promise<number>`:
44
-
45
- - `0` — правило відпрацювало успішно, порушень немає (або всі виправлені автоматично, якщо це fix-режим);
46
- - `1` — виявлено порушення, які не вдалося виправити автоматично.
47
-
48
- **Side effects.**
49
-
50
- - Може **читати** файли проєкту (через walk у `runStandardRule`).
51
- - Може **записувати/змінювати** файли проєкту, якщо стандартний пайплайн застосовує автоматичні фіксери.
52
- - Може **писати у stdout/stderr** діагностичні повідомлення стандартного пайплайну.
53
- - **Не** викликає `process.exit` — рішення про exit-code залишається за викликачем.
54
-
55
- **Ключовий момент.** Перший аргумент `runStandardRule` — `import.meta.dirname` — це абсолютний шлях до директорії, у якій лежить `fix.mjs` (тобто `…/npm/rules/js-bun-db/`). За цим шляхом `runStandardRule` визначає **id правила** і завантажує його `.mdc`, `check-*.mjs`, тощо.
56
-
57
- ## Залежності
8
+ # fix.mjs
58
9
 
59
- ### Внутрішні модулі (npm/scripts/lib)
60
-
61
- | Імпорт | Звідки | Роль |
62
- | ----------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
63
- | `isRunAsCli` | `../../scripts/lib/run-rule-cli.mjs` | Утиліта-детектор: повертає `true`, якщо переданий `import.meta.url` відповідає файлу, який запущено як головний модуль (`process.argv[1]`). Дозволяє відрізнити library-import від standalone-запуску. |
64
- | `runRuleCli` | `../../scripts/lib/run-rule-cli.mjs` | Standalone CLI orchestration: завантажує конфіг (`.cursor.json`/`package.json`), застосовує whitelist, запускає правило з директорії, друкує summary і повертає `Promise<number>` (exit-code). |
65
- | `runStandardRule` | `../../scripts/lib/run-standard-rule.mjs` | Бібліотечний прогон стандартного пайплайну правила (`applies → JS-concerns → policy → mdc-refs`). Не виконує CLI-обв'язку (конфіг, summary). |
66
-
67
- ### Системні API
68
-
69
- | API | Використання |
70
- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
71
- | `import.meta.dirname` | Абсолютний шлях до директорії, що містить цей `fix.mjs`. Передається у `runStandardRule` та `runRuleCli` як ідентифікатор правила. |
72
- | `import.meta.url` | URL поточного модуля. Передається в `isRunAsCli` для перевірки, чи запущено модуль як CLI. |
73
- | `process.exit` | Викликається лише у standalone-гілці з кодом, поверненим `runRuleCli`. Дає змогу CI/IDE отримати exit-status. |
74
-
75
- ### ESLint-директива
76
-
77
- Файл містить рядкову директиву:
78
-
79
- ```text
80
- // eslint-disable-next-line n/no-process-exit, unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
81
- ```
82
-
83
- Свідоме вимкнення правил `n/no-process-exit` та `unicorn/no-process-exit` для рядка з `process.exit`. Виправдання: standalone entry-point **зобов'язаний** повертати exit-code для CI/IDE-консьюмерів.
84
-
85
- ## Потік виконання / Використання
86
-
87
- ### Дві ролі модуля
88
-
89
- Файл проектувався так, щоб **той самий код** обслуговував і library-, і standalone-сценарії, без дублювання логіки.
90
-
91
- #### Library mode (import + run)
92
-
93
- ```js
94
- import { run } from '@nitra/cursor/rules/js-bun-db/fix.mjs'
95
-
96
- const exitCode = await run({ walkCache })
97
- // ^^^^^^^^ 0 = OK, 1 = порушення
98
- ```
99
-
100
- - Викликач (наприклад, головний CLI `@nitra/cursor`) уже завантажив конфіг, побудував список правил, створив спільний `walkCache`.
101
- - Викликає `run(ctx)`, отримує число (exit-code-семантика), сам приймає рішення про `process.exit`.
102
- - Гілка `if (isRunAsCli(...))` **не виконується**, бо `import.meta.url` цього файлу не збігається з URL головного модуля процесу.
103
-
104
- #### Standalone mode (bun rules/js-bun-db/fix.mjs)
105
-
106
- ```bash
107
- bun npm/rules/js-bun-db/fix.mjs
108
- # еквівалентно:
109
- npx @nitra/cursor fix js-bun-db
110
- ```
111
-
112
- - Bun запускає `fix.mjs` як головний модуль.
113
- - `isRunAsCli(import.meta.url)` повертає `true`.
114
- - Виконується `await runRuleCli(import.meta.dirname)` — повний CLI-цикл: завантаження конфігурації, whitelist-фільтрація, прогон, друк підсумку.
115
- - Результат (number) передається у `process.exit`, який завершує процес із потрібним exit-code для CI/IDE.
116
-
117
- ### Послідовність кроків при standalone-запуску
118
-
119
- 1. Інтерпретатор виконує верхньорівневі імпорти (`isRunAsCli`, `runRuleCli`, `runStandardRule`).
120
- 2. Створюється/реєструється функція `run` (експорт).
121
- 3. Перевіряється `isRunAsCli(import.meta.url)` — для standalone дає `true`.
122
- 4. Викликається `await runRuleCli(import.meta.dirname)` — повертає `Promise<number>`.
123
- 5. `process.exit(<number>)` завершує процес.
10
+ ## Огляд
124
11
 
125
- ### Послідовність кроків при library-import
12
+ Виконує застосування JS-занепокоєних на наданому контексті прогону. Застосовує визначену політику та генерує посилання MDC. Повертає результат прогону.
126
13
 
127
- 1. Інтерпретатор виконує верхньорівневі імпорти.
128
- 2. Створюється функція `run` (експорт стає доступним викликачу).
129
- 3. `isRunAsCli(...)` повертає `false` — гілка `if (...)` пропускається.
130
- 4. Модуль готовий: викликач у будь-який момент викликає `run(ctx)`.
14
+ ## Поведінка
131
15
 
132
- ### Архітектурні нотатки
16
+ 1. Запуск правила.
17
+ * Приймає контекст прогону.
18
+ * Виконує застосування JS-занепокоєних.
19
+ * Застосовує політику.
20
+ * Генерує посилання MDC.
21
+ * Повертає результат прогону.
133
22
 
134
- - **Чому два режими в одному файлі.** Така подвійна роль (`library + standalone`) — конвенція пакета `@nitra/cursor` для всіх `fix.mjs` правил. Це дає:
135
- - можливість швидко прогнати **одне правило** локально під час розробки (`bun rules/<id>/fix.mjs`);
136
- - можливість CLI-оркестратору **імпортувати** правило без форку процесу;
137
- - єдиний контракт (`run(ctx) → Promise<number>`) для всіх правил пакета.
138
- - **Чому `import.meta.dirname`.** Це абсолютний шлях, який не залежить від CWD виклику; правило знаходить свої артефакти (`.mdc`, `check-*.mjs`, `meta.json`) відносно власного розташування на диску.
139
- - **Чому `await` перед `runRuleCli`.** `runRuleCli` — асинхронна функція; `process.exit` має отримати готове число, а не `Promise`.
23
+ ## Публічний API
140
24
 
141
- ## Rebuild Test
25
+ run запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
26
+ Library mode — викликається CLI orchestration через `import + run`.
142
27
 
143
- З опису вище можна реконструювати поведінку файлу:
28
+ ## Гарантії поведінки
144
29
 
145
- 1. **Імпорти.** Дві утиліти з `../../scripts/lib/run-rule-cli.mjs` (`isRunAsCli`, `runRuleCli`) та одна з `../../scripts/lib/run-standard-rule.mjs` (`runStandardRule`).
146
- 2. **Експорт `run(ctx)`.** Повертає `runStandardRule(import.meta.dirname, ctx)`. Сигнатура: `(ctx?: RuleContext) => Promise<number>`. `0` — OK, `1` — порушення.
147
- 3. **CLI-блок.** Умова `if (isRunAsCli(import.meta.url))`. Усередині — `process.exit(await runRuleCli(import.meta.dirname))`. Перед `process.exit` стоїть `eslint-disable-next-line` для `n/no-process-exit` та `unicorn/no-process-exit` із поясненням, що standalone entry-point має повертати exit-code.
148
- 4. **Жодної іншої логіки.** Файл не містить ні констант, ні класів, ні допоміжних функцій — лише делегування.
30
+ - Read-only: файл не виконує операцій запису у файлову систему.
31
+ - Кешує результати в межах одного прогону.
32
+ - Не звертається до мережі.
@@ -1,231 +1,43 @@
1
- # `safety.mjs` — перевірка правила `js-bun-db.mdc`
1
+ ---
2
+ docgen:
3
+ source: npm/rules/js-bun-db/js/safety.mjs
4
+ crc: eaeb52bc
5
+ score: 100
6
+ ---
2
7
 
3
- ## Огляд
4
-
5
- Модуль `npm/rules/js-bun-db/js/safety.mjs` — основний JS-чекер правила `js-bun-db.mdc`. Його завдання — обійти репозиторій і переконатися, що проєкт використовує **Bun native SQL** (`import { sql, SQL } from 'bun'`) замість застарілих PostgreSQL/MySQL клієнтів, та що Bun SQL використовується безпечно.
6
-
7
- Чекер виконує три великі групи перевірок:
8
-
9
- 1. **Заборона `pg-format` / `mysql2`** у `dependencies` будь-якого `package.json`. Цю частину закриває окремий Rego-поліс у `npm/policy/js_bun_db/package_json/` — `safety.mjs` лише довіряє йому й не дублює перевірку.
10
- 2. **Виключення для `pg`** — dependency `pg` дозволено тільки тоді, коли в коді справді використовується `LISTEN` / `NOTIFY` / `UNLISTEN` або listener `.on('notification', ...)` (Bun SQL поки не покриває LISTEN/NOTIFY). Перевірка йде на двох рівнях: на рівні кожного `package.json` (якщо в проекті взагалі немає LISTEN/NOTIFY — `pg` забороняється) і per-file (файл з `import 'pg'` сам має містити LISTEN/NOTIFY-патерн).
11
- 3. **Безпечне використання Bun SQL** у файлах з `import { sql|SQL } from 'bun'`. Сюди входять перевірки на `new SQL(...)` у функції (має бути модульний singleton), `sql.unsafe(...)` без маркера-коментаря `// allow-unsafe: <reason>`, динамічні `.join(',')` у `IN (...)` / `VALUES (...)`, IN-списки без guard на пустоту, pg-format-сумісні шими (`format` / `quoteLiteral` / `quoteIdent`) і `query(text, params)`-обгортки над `<obj>.unsafe(...)`.
12
-
13
- Усі знайдені порушення повідомляються через `createCheckReporter()` як `fail`, а кожна «чиста» категорія дає окремий `pass`. Підсумкове значення — `0` (все чисто) або `1` (є порушення) — повертає функція `check`.
14
-
15
- ## Експорти / API
16
-
17
- | Експорт | Тип | Призначення |
18
- | ------------- | ---------------- | ---------------------------------------------------------------------------------------------------- |
19
- | `check(cwd?)` | `async function` | Публічна точка входу. Виконує всі перевірки правила `js-bun-db.mdc` і повертає exit-код (`0` / `1`). |
20
-
21
- Решта функцій (`findAllSourcePathsForBunSqlScan`, `scanSourcesForBunSqlPatterns`, `collectPgUsageForFile`, `scanFileForBunSqlPatterns`, `checkPgDependencyAndUsage`, `messageForBunSqlInListGuard`) — внутрішні; з модуля не експортуються.
22
-
23
- Константи модульного скоупу (теж не експортуються):
24
-
25
- - `LISTEN_NOTIFY_KEYWORD_RE` — `/\b(LISTEN|UNLISTEN|NOTIFY)\b/iu`. Дешевий pre-filter regex для пошуку SQL-ключових слів.
26
- - `NOTIFICATION_LITERAL_RE` — `/['"`]notification['"`]/u`. Дешевий pre-filter regex для рядкового літерала `'notification'`(як ім'я події в`.on('notification', ...)`).
27
-
28
- Обидві винесені у модульний скоуп, щоб не перекомпілювати `RegExp` на кожен виклик `collectPgUsageForFile`.
29
-
30
- ## Функції
31
-
32
- ### `findAllSourcePathsForBunSqlScan(repoRoot, ignorePaths)`
33
-
34
- - **Сигнатура:** `async function findAllSourcePathsForBunSqlScan(repoRoot: string, ignorePaths: string[]): Promise<string[]>`
35
- - **Параметри:**
36
- - `repoRoot` — абсолютний шлях до кореня репозиторію.
37
- - `ignorePaths` — масив абсолютних шляхів каталогів, які повністю виключаються з обходу (звичайно отримується з `loadCursorIgnorePaths`).
38
- - **Повертає:** масив абсолютних шляхів файлів, що проходять `isBunSqlScanSourceFile(rel)`, відсортований за відносним posix-шляхом (через `localeCompare`).
39
- - **Side effects:** виключно читання директорій через `walkDir`; нічого не пише.
40
- - **Деталі:** використовує `walkDir` із зовнішнього колбека: для кожного знайденого `absPath` обчислює відносний шлях, нормалізує windows-роздільники (`\\` → `/`) і викликає `isBunSqlScanSourceFile`. Сортування потрібне, щоб порядок повідомлень про порушення був детермінованим.
41
-
42
- ### `scanSourcesForBunSqlPatterns(sourcePaths, repoRoot, reporter)`
43
-
44
- - **Сигнатура:** `async function scanSourcesForBunSqlPatterns(sourcePaths: string[], repoRoot: string, reporter: { pass: (m: string) => void, fail: (m: string) => void }): Promise<{ hasBunSqlImport: boolean, perRequest: number, unsafeCall: number, unsafeTemplateInterp: number, dynamicList: number, inListGuard: number, pgLeftover: number, pgFormatShim: number, queryWrapper: number, pgUsage: Array<{ rel: string, imports: { line: number, snippet: string }[], listenNotify: { line: number, snippet: string, kind: string }[] }> }>`
45
- - **Параметри:**
46
- - `sourcePaths` — абсолютні шляхи джерел, відібраних `findAllSourcePathsForBunSqlScan`.
47
- - `repoRoot` — абсолютний шлях до кореня.
48
- - `reporter` — обʼєкт з `pass`/`fail` (тут використовується лише `fail`).
49
- - **Повертає:** обʼєкт з прапором `hasBunSqlImport`, лічильниками порушень за категоріями (`perRequest`, `unsafeCall`, `unsafeTemplateInterp`, `dynamicList`, `inListGuard`, `pgLeftover`, `pgFormatShim`, `queryWrapper`) та масивом `pgUsage` (тільки файли з імпортом `'pg'` або LISTEN/NOTIFY-патерном).
50
- - **Side effects:** читає файли через `readFile`; викликає `fail(...)` для кожного порушення (через `scanFileForBunSqlPatterns`).
51
- - **Деталі:** проходить по всіх файлах послідовно (`for ... of`), щоб не створювати лавину паралельних `readFile`. Прапор `hasBunSqlImport` встановлюється тільки один раз — після першого знайденого `import { sql|SQL } from 'bun'`. У повернутому обʼєкті лічильник `unsafeTemplateInterp` присутній фактично, хоча у JSDoc-типі формально не задекларований (важлива деталь для подальшого використання у `check`).
52
-
53
- ### `collectPgUsageForFile(content, rel, pgUsage)`
54
-
55
- - **Сигнатура:** `function collectPgUsageForFile(content: string, rel: string, pgUsage: Array<{ rel, imports, listenNotify }>): void`
56
- - **Параметри:**
57
- - `content` — повний вміст файлу.
58
- - `rel` — posix-шлях відносно кореня репо.
59
- - `pgUsage` — масив-акумулятор (мутується in place).
60
- - **Повертає:** нічого.
61
- - **Side effects:** мутує `pgUsage` через `push`.
62
- - **Деталі:**
63
- 1. Дешевий текстовий pre-filter: `mayHaveListenNotify = LISTEN_NOTIFY_KEYWORD_RE.test(content) || NOTIFICATION_LITERAL_RE.test(content)`.
64
- 2. Якщо файл не імпортує `'pg'` І не пройшов pre-filter — швидкий `return` (AST не парситься).
65
- 3. Інакше викликаються AST-сканери `findPgLibImportInText` і `findPgListenNotifyUsageInText`.
66
- 4. Якщо обидва пусті — запис не додається.
67
- 5. Інакше у `pgUsage` пушиться `{ rel, imports, listenNotify }`.
68
-
69
- Логіка економить памʼять (не зберігаються метадані файлів без сигналу) і CPU (AST не парситься для файлів без жодного зі слів LISTEN / NOTIFY / UNLISTEN / `'notification'` і без імпорту `'pg'`).
70
-
71
- ### `scanFileForBunSqlPatterns(content, rel, fail, counts)`
8
+ # safety.mjs
72
9
 
73
- - **Сигнатура:** `function scanFileForBunSqlPatterns(content: string, rel: string, fail: (msg: string) => void, counts: { perRequest, unsafeCall, unsafeTemplateInterp, dynamicList, inListGuard, pgLeftover, pgFormatShim, queryWrapper }): void`
74
- - **Параметри:**
75
- - `content` — вміст файлу.
76
- - `rel` — posix-шлях відносно `repoRoot`.
77
- - `fail` — колбек з reporter'а для запису повідомлень про порушення.
78
- - `counts` — обʼєкт-акумулятор лічильників (мутується).
79
- - **Повертає:** нічого.
80
- - **Side effects:** інкрементує лічильники `counts.*` та викликає `fail(...)` для кожного знайденого порушення.
81
- - **Деталі:** запускає по черзі сімейство сканерів з `bun-sql-scan.mjs`:
82
-
83
- | Сканер | Лічильник | Тип порушення |
84
- | ------------------------------------------------ | ---------------------- | --------------------------------------------------------------------------------------------------------------------- |
85
- | `findBunSqlPerRequestConnectionInText` | `perRequest` | `new SQL(...)` всередині функції — має бути модульний singleton. |
86
- | `findBunSqlUnsafeUseWithoutAllowMarkerInText` | `unsafeCall` | `<obj>.unsafe(...)` без маркера `// allow-unsafe: <reason>` на тому ж/попередньому рядку. |
87
- | `findBunSqlUnsafeWithInterpolatedTemplateInText` | `unsafeTemplateInterp` | `sql.unsafe(\`...\${x}...\`)` з template-літералом + інтерполяцією (заборонено навіть з allow-маркером). |
88
- | `findBunSqlPgLeftoverCallInText` | `pgLeftover` | `<obj>.connect(...)` / `<obj>.end(...)` у файлах з Bun SQL (Bun сам керує пулом). |
89
- | `findUnsafeBunSqlDynamicSqlListInText` | `dynamicList` | Динамічний список через `.join(',')` у `IN (...)` / `VALUES (...)`. |
90
- | `findUnsafeBunSqlInListMissingEmptyGuardInText` | `inListGuard` | IN-список без перевірки на пустоту з `throw` — повідомлення формує `messageForBunSqlInListGuard`. |
91
- | `findPgFormatShimDefinitionInText` | `pgFormatShim` | Локальне визначення pg-format-сумісного шиму (`format` з `%L` / `%I` / `%s`, або `quoteLiteral` / `quoteIdent` тощо). |
92
- | `findPgFormatLikeQueryWrapperInText` | `queryWrapper` | `query(text, params)` обгортка над `<obj>.unsafe(...)` — прихований pg-сумісний шим. |
93
-
94
- Кожне повідомлення містить шлях, номер рядка, людський опис проблеми, посилання на правило `js-bun-db.mdc` і сам snippet порушення. Для `findPgFormatShimDefinitionInText` повідомлення розгалужується за `v.kind === 'format_function'` (повна функція з форматерами) vs інше (escape-хелпер на кшталт `quoteLiteral`).
95
-
96
- ### `checkPgDependencyAndUsage(pkgJsonPaths, repoRoot, pgUsage, reporter)`
97
-
98
- - **Сигнатура:** `async function checkPgDependencyAndUsage(pkgJsonPaths: string[], repoRoot: string, pgUsage: Array<{ rel, imports, listenNotify }>, reporter: { fail: (m: string) => void }): Promise<{ pgDepFails: number, pgImportFails: number, pgDepsFound: number, hasAnyListenNotify: boolean, listenNotifyEvidence: string | null }>`
99
- - **Параметри:**
100
- - `pkgJsonPaths` — абсолютні шляхи всіх знайдених `package.json`.
101
- - `repoRoot` — корінь репозиторію.
102
- - `pgUsage` — метадані з `scanSourcesForBunSqlPatterns`.
103
- - `reporter` — обʼєкт з `fail`.
104
- - **Повертає:** обʼєкт зі статистикою:
105
- - `pgDepFails` — скільки `package.json` мають `dependencies.pg` без підтвердженого LISTEN/NOTIFY у проекті.
106
- - `pgImportFails` — скільки окремих файлів-імпортів `'pg'` не мають власного LISTEN/NOTIFY.
107
- - `pgDepsFound` — скільки `package.json` оголошують `dependencies.pg` (для `pass`-повідомлення про виключення).
108
- - `hasAnyListenNotify` — чи хоч десь у проекті є LISTEN/NOTIFY.
109
- - `listenNotifyEvidence` — рядок виду `"<rel>:<line>"` — перший доказ LISTEN/NOTIFY (або `null`).
110
- - **Side effects:** читає `package.json` через `readFile`; викликає `reporter.fail(...)` за кожне порушення.
111
- - **Деталі:**
112
- 1. Спочатку шукає у `pgUsage` перший файл з непустим `listenNotify` (`firstWithListenNotify`) — фіксується доказ (`<rel>:<firstLine>`).
113
- 2. Цикл по `pkgJsonPaths`: парсить кожен `package.json` (`JSON.parse`), на невалідному — `continue` (це проблема інших правил). Якщо немає `dependencies.pg` — пропускає. Інакше інкрементує `pgDepsFound` і, якщо у проекті немає LISTEN/NOTIFY взагалі, інкрементує `pgDepFails` та пише `fail` про заборону `dependencies.pg`.
114
- 3. Цикл по `pgUsage`: для кожного файлу з імпортом `'pg'`, але без LISTEN/NOTIFY — інкрементує `pgImportFails` і пише `fail` по кожному імпорту окремо.
115
-
116
- ### `messageForBunSqlInListGuard(rel, v)`
117
-
118
- - **Сигнатура:** `function messageForBunSqlInListGuard(rel: string, v: { line: number, snippet: string, name?: string, reason: string }): string`
119
- - **Параметри:**
120
- - `rel` — posix-шлях файлу.
121
- - `v` — обʼєкт порушення від `findUnsafeBunSqlInListMissingEmptyGuardInText`: містить `line`, `snippet`, опційне `name` (ідентифікатор змінної) і `reason` (підвид діагностики).
122
- - **Повертає:** готовий рядок-повідомлення для `fail`.
123
- - **Side effects:** немає; чиста функція.
124
- - **Деталі:** діагностика розгалужується за `v.reason`:
125
- - `'missing_guard'` — змінна-IN не має перевірки на пустоту з `throw`.
126
- - `'sql_helper_not_var'` — у `${sql(...)}` всередині IN-списку має бути Identifier (а не вираз/виклик).
127
- - інакше (default) — значення IN-списку у template literal треба винести в окрему змінну, валідувати на пустоту і кинути `throw` замість прямої підстановки.
128
-
129
- ### `check(cwd?)`
130
-
131
- - **Сигнатура:** `export async function check(cwd: string = process.cwd()): Promise<number>`
132
- - **Параметри:**
133
- - `cwd` — корінь репозиторію; за замовчуванням `process.cwd()`.
134
- - **Повертає:** `0`, якщо порушень не знайдено; `1` — інакше. Точне значення обчислює `reporter.getExitCode()`.
135
- - **Side effects:** читання файлів (`existsSync`, `readFile`, `walkDir`); виклики `reporter.pass(...)` / `reporter.fail(...)` (у дефолтній імплементації — друкують у консоль).
136
- - **Деталі (порядок виконання):**
137
- 1. Створює reporter через `createCheckReporter()`; деструктурує `{ pass }`.
138
- 2. Перевіряє існування `package.json` у корені. Якщо немає — `pass('js-bun-db: package.json у корені відсутній — перевірку пропущено')` і ранній вихід.
139
- 3. Підвантажує `ignorePaths` через `loadCursorIgnorePaths(repoRoot)` (читає `.cursorignore` тощо).
140
- 4. Шукає всі `package.json` у репо (`findAllPackageJsonPaths`). Якщо нічого — `pass(...)` і вихід.
141
- 5. Збирає всі JS/TS-джерела для скану (`findAllSourcePathsForBunSqlScan`). Якщо нічого — `pass(...)` і вихід.
142
- 6. Сканує всі джерела (`scanSourcesForBunSqlPatterns`) і отримує лічильники + `pgUsage` + `hasBunSqlImport`.
143
- 7. Перевіряє dependency `pg` і per-file імпорти (`checkPgDependencyAndUsage`). На основі `pgDepFails === 0` / `pgImportFails === 0` пише відповідні `pass`-повідомлення (з різним текстом залежно від `pgDepsFound`).
144
- 8. Якщо `hasBunSqlImport === false` — `pass('Bun SQL не використовується в коді')` і ранній вихід (немає сенсу скаржитися на патерни Bun SQL у проекті, що ним не користується).
145
- 9. Інакше для кожної категорії з `count === 0` пише позитивний `pass` (`new SQL` singleton, `sql.unsafe` маркерована, `unsafeTemplateInterp`, pg-leftover, dynamic list, in-list guard, pg-format шими, query-обгортки).
146
- 10. Повертає `reporter.getExitCode()`.
147
-
148
- ## Залежності
149
-
150
- Зовнішні (Node.js core):
151
-
152
- - `node:fs` → `existsSync` — перевірка наявності кореневого `package.json`.
153
- - `node:fs/promises` → `readFile` — асинхронне читання файлів.
154
- - `node:path` → `join`, `relative` — побудова шляхів і обчислення відносних.
155
-
156
- Внутрішні модулі репозиторію:
157
-
158
- - `../../../scripts/lib/check-reporter.mjs` → `createCheckReporter` — фабрика reporter'а з `pass` / `fail` / `getExitCode`.
159
- - `../lib/bun-sql-scan.mjs` — набір AST-сканерів і дешевих текстових пре-фільтрів:
160
- - `findBunSqlPerRequestConnectionInText`
161
- - `findBunSqlPgLeftoverCallInText`
162
- - `findBunSqlUnsafeUseWithoutAllowMarkerInText`
163
- - `findBunSqlUnsafeWithInterpolatedTemplateInText`
164
- - `findPgFormatLikeQueryWrapperInText`
165
- - `findPgFormatShimDefinitionInText`
166
- - `findPgLibImportInText`
167
- - `findPgListenNotifyUsageInText`
168
- - `findUnsafeBunSqlDynamicSqlListInText`
169
- - `findUnsafeBunSqlInListMissingEmptyGuardInText`
170
- - `isBunSqlScanSourceFile` — фільтр шляхів (які файли скануються взагалі).
171
- - `textHasBunSqlImport` — швидкий текстовий тест на наявність `import { sql|SQL } from 'bun'`.
172
- - `textHasPgLibImport` — швидкий текстовий тест на наявність `import ... from 'pg'`.
173
- - `../../../scripts/utils/find-package-json-paths.mjs` → `findAllPackageJsonPaths` — обхід репо і збір усіх `package.json` (з урахуванням ignore-паттернів).
174
- - `../../../scripts/lib/load-cursor-config.mjs` → `loadCursorIgnorePaths` — список абсолютних шляхів, виключених з обходу (на основі конфігу Cursor).
175
- - `../../../scripts/utils/walkDir.mjs` → `walkDir` — рекурсивний обхід каталогу з підтримкою ignore-list.
176
-
177
- Покладається на наявність ESM, `bun`/`node` runtime з підтримкою top-level `process.cwd()`.
178
-
179
- ## Потік виконання / Використання
180
-
181
- ### Імпорт як бібліотека
182
-
183
- ```js
184
- import { check } from './safety.mjs'
185
-
186
- const exitCode = await check(process.cwd())
187
- process.exit(exitCode)
188
- ```
10
+ ## Огляд
189
11
 
190
- ### Запуск у складі checker-пайплайна
12
+ Огляд
191
13
 
192
- Функція `check(cwd)` це стандартний контракт правил `npm/rules/<rule-id>/js/safety.mjs` у репозиторії. Зовнішній runner викликає її, отримує `0` / `1` і за потреби агрегує з іншими правилами.
14
+ Файл перевіряє шляхи до файлів та залежностей, пов'язаних з Bun SQL та бібліотекою `pg`. Файл збирає метадані про використання `pg` та механізми LISTEN/NOTIFY. (js-bun-db.mdc)
193
15
 
194
- ### Логічний потік `check`
16
+ ## Поведінка
195
17
 
196
- ```
197
- check(cwd)
198
- ├── existsSync(<cwd>/package.json)? // ні pass + exit
199
- ├── loadCursorIgnorePaths(repoRoot)
200
- ├── findAllPackageJsonPaths(...) // 0 pass + exit
201
- ├── findAllSourcePathsForBunSqlScan(...) // 0 pass + exit
202
- ├── scanSourcesForBunSqlPatterns(...)
203
- │ для кожного файлу:
204
- │ ├── textHasBunSqlImport встановити hasBunSqlImport
205
- │ ├── scanFileForBunSqlPatterns 8 сканерів, fail + counts
206
- │ └── collectPgUsageForFile текст-prefilter → AST → push pgUsage
207
- ├── checkPgDependencyAndUsage(...)
208
- │ ├── знайти firstWithListenNotify → listenNotifyEvidence
209
- │ ├── по кожному package.json з dependencies.pg → fail якщо нема LISTEN/NOTIFY
210
- │ └── по кожному файлу з import 'pg' без LISTEN/NOTIFY → fail
211
- ├── pass-повідомлення про pg (залежно від pgDepsFound / listenNotifyEvidence)
212
- ├── якщо !hasBunSqlImport → pass + exit
213
- └── pass для кожної категорії з count === 0
214
- (perRequest, unsafeCall, unsafeTemplateInterp,
215
- pgLeftover, dynamicList, inListGuard,
216
- pgFormatShim, queryWrapper)
217
- └── return reporter.getExitCode()
218
- ```
18
+ 1. Завантажити шляхи до файлів з коду
19
+ 2. Просканувати джерела за патернами Bun SQL
20
+ 3. Зібрати метадані про використання `pg` та LISTEN/NOTIFY
21
+ 4. Перевірити залежності `pg` та використання LISTEN/NOTIFY
22
+ 5. Перевірити імпорти `pg` та використання LISTEN/NOTIFY
23
+ 6. Перевірити наявність `package.json` для залежностей `pg`
24
+ 7. Перевірити використання `import { sql|SQL } from 'bun'`
25
+ 8. Перевірити відсутність створення `new SQL` всередині функцій
26
+ 9. Перевірити використання `sql.unsafe` без маркерів дозволу
27
+ 10. Перевірити використання `sql.unsafe` з template-літералами
28
+ 11. Перевірити використання `pg-leftover` викликів
29
+ 12. Перевірити використання `findBunSqlUnsafeBunSqlDynamicSqlListInText`
30
+ 13. Перевірити використання `findUnsafeBunSqlInListMissingEmptyGuardInText`
31
+ 14. Перевірити використання `findPgFormatShimDefinitionInText`
32
+ 15. Перевірити використання `findPgFormatLikeQueryWrapperInText`
33
+ 16. Перевірити наявність використання `import { sql } from 'bun'`
219
34
 
220
- ### Як інтерпретувати вивід
35
+ ## Публічний API
221
36
 
222
- - Кожне порушення друкується через `fail(...)` з префіксом `js-bun-db:`, шляхом `<rel>:<line>`, описом і snippet.
223
- - Кожна чиста категорія дає `pass(...)` — це корисно для логів CI, щоб бачити, що перевірка не «мовчки» пропущена.
224
- - Exit-код `0` гарантує, що жоден `fail` не був викликаний; `1` — є щонайменше один.
37
+ check Перевіряє відповідність проєкту правилу js-bun-db.mdc
225
38
 
226
- ### Сценарії раннього виходу
39
+ ## Гарантії поведінки
227
40
 
228
- - Корінь без `package.json` нічого перевіряти.
229
- - `package.json` не знайдено взагалі те саме.
230
- - Немає файлів для скану (`isBunSqlScanSourceFile` повернув `false` для всіх) — Bun SQL-патерни ніде шукати.
231
- - У жодному файлі немає `import { sql|SQL } from 'bun'` — у проекті немає Bun SQL, тож перевірки на `new SQL`, `unsafe`, IN-списки тощо нерелевантні. Перевірка `pg`-dependency при цьому виконується завжди (до цього раннього виходу), бо її цінність не залежить від Bun SQL.
41
+ - Read-only: файл не виконує операцій запису у файлову систему.
42
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
43
+ - Не звертається до мережі.
@@ -1,123 +1,34 @@
1
- # fix.mjs — правило `js-bun-redis`
1
+ ---
2
+ docgen:
3
+ source: npm/rules/js-bun-redis/fix.mjs
4
+ crc: 38cf876b
5
+ score: 80
6
+ ---
2
7
 
3
- ## Огляд
4
-
5
- Файл `npm/rules/js-bun-redis/fix.mjs` — це тонкий **entry-point** правила `js-bun-redis` у системі `@nitra/cursor`. Він не містить власної бізнес-логіки перевірки/виправлення: уся робота (resolve `applies`, JS-concerns, policy, mdc-refs) делегується утиліті `runStandardRule`, а CLI-обгортка — `runRuleCli`.
6
-
7
- Файл реалізує **дві ролі одночасно**:
8
-
9
- 1. **Library mode** — інші модулі імпортують функцію `run(ctx)` і запускають правило в межах загального оркестрування (наприклад, `npx @nitra/cursor fix` обходить набір правил, передаючи спільний `walkCache` через `ctx`).
10
- 2. **Standalone mode** — пряме виконання через `bun npm/rules/js-bun-redis/fix.mjs`. У цьому випадку модуль самостійно завантажує конфіг, застосовує whitelist і друкує summary, повертаючи коректний exit-code для CI/IDE.
11
-
12
- Правило `js-bun-redis` належить до родини "standard rules" і параметризується тим, що `runStandardRule` отримує `import.meta.dirname` поточної теки — далі допоміжна бібліотека сама читає `meta.json`, `applies.mjs`, `check-*.mjs` тощо, які знаходяться поруч у каталозі `npm/rules/js-bun-redis/`.
13
-
14
- ## Експорти / API
15
-
16
- | Експорт | Тип | Опис |
17
- | ------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
18
- | `run` | `function (ctx?) => Promise<number>` | Іменований експорт. Запускає правило в library-режимі. Сумісний із загальним runner-ом, який очікує сигнатуру `run(ctx)`. |
19
-
20
- Default-експорту немає. Side-effect-ний блок наприкінці файлу не експортується — він активний лише при прямому виконанні модуля як CLI.
21
-
22
- ## Функції
23
-
24
- ### `run(ctx)`
25
-
26
- ```js
27
- export function run(ctx)
28
- ```
29
-
30
- - **Сигнатура:** `run(ctx?: RuleContext): Promise<number>`
31
- - **Параметри:**
32
- - `ctx` (необовʼязковий) — обʼєкт контексту прогону правила (`RuleContext`, тип реекспортовано з `../../scripts/lib/run-standard-rule.mjs`). Типово містить кешовані результати обходу файлової системи (`walkCache`) та інші спільні структури, які передаються між правилами під час оркестрованого прогону. Якщо викликати без аргументу — `runStandardRule` створить локальний контекст самостійно.
33
- - **Повертає:** `Promise<number>` — exit-код:
34
- - `0` — правило пройшло без порушень,
35
- - `1` — знайдено порушення (`runStandardRule` сам формує summary з деталями знайдених проблем у stdout/stderr).
36
- - **Side effects:**
37
- - Читання файлів проєкту, які матчаться `applies.mjs` цього правила.
38
- - Логування результатів (summary) у stdout залежить від внутрішньої поведінки `runStandardRule`.
39
- - Безпосередньо у `fix.mjs` ніяких глобальних мутацій, мережевих викликів чи запису у ФС немає — все інкапсульовано в делегованих бібліотеках.
40
-
41
- ### CLI-блок (top-level, без імені)
8
+ # fix.mjs
42
9
 
43
- ```js
44
- if (isRunAsCli(import.meta.url)) {
45
- process.exit(await runRuleCli(import.meta.dirname))
46
- }
47
- ```
48
-
49
- - **Умова:** `isRunAsCli(import.meta.url)` повертає `true`, коли цей файл є entry-point поточного Node/Bun-процесу (а не імпортується з іншого модуля).
50
- - **Дія:** виконує `await runRuleCli(import.meta.dirname)` — повний еквівалент `npx @nitra/cursor fix <id>`, включно з:
51
- - завантаженням конфігурації,
52
- - застосуванням whitelist,
53
- - друком підсумкового summary.
54
- - **Завершення процесу:** результат (числовий exit-code) передається у `process.exit(...)`, що зупиняє процес із потрібним статусом для CI / IDE-інтеграції.
55
- - **ESLint-винятки:**
56
- - `n/no-process-exit` та `unicorn/no-process-exit` локально відключено через те, що standalone-точка входу зобовʼязана повертати числовий exit-code (інакше CI не побачить статус правила).
57
-
58
- ## Залежності
59
-
60
- ### Внутрішні модулі
61
-
62
- - `../../scripts/lib/run-rule-cli.mjs` — реекспортує:
63
- - `isRunAsCli(metaUrl)` — детектор того, чи виконується модуль як CLI entry-point.
64
- - `runRuleCli(dirname)` — повна CLI-обгортка для одного правила.
65
- - `../../scripts/lib/run-standard-rule.mjs` — реекспортує:
66
- - `runStandardRule(dirname, ctx?)` — стандартний пайплайн для "звичайного" правила: `applies` → JS-concerns → policy → mdc-refs.
67
- - JSDoc-тип `RuleContext` (використовується лише в анотації параметра `ctx`).
68
-
69
- ### Сусідні артефакти правила (читаються опосередковано через `runStandardRule` / `runRuleCli`)
70
-
71
- - `npm/rules/js-bun-redis/meta.json` — метаінформація правила (id, severity, applies-патерни, посилання на `.mdc` тощо).
72
- - `npm/rules/js-bun-redis/applies.mjs` — фільтр файлів, до яких застосовується правило.
73
- - `npm/rules/js-bun-redis/check-*.mjs` — конкретні перевірки JS-concerns.
74
- - `npm/rules/js-bun-redis/policy.mjs` (за наявності) — policy-шар.
75
- - Звʼязаний `.mdc` у каталозі `mdc/` — людинозрозумілий опис правила (`mdc-refs`-перевірка переконується, що посилання збігаються).
76
-
77
- ### Зовнішні залежності
78
-
79
- Прямих імпортів npm-пакетів у файлі немає. Усі сторонні залежності (наприклад, `fs`, `path` тощо) приходять транзитивно через `runStandardRule` / `runRuleCli`.
80
-
81
- ### Глобалі та середовище виконання
82
-
83
- - `import.meta.dirname` — абсолютний шлях до теки `npm/rules/js-bun-redis/`. Використовується як ідентифікатор правила (`runStandardRule` із `dirname` зчитує `meta.json` та інші файли поруч).
84
- - `import.meta.url` — URL поточного модуля. Передається в `isRunAsCli` для детекту режиму запуску.
85
- - `process.exit(code)` — глобальний Node/Bun API. Використовується **виключно** у standalone-режимі.
86
- - Підтримка top-level `await` — обовʼязкова; код розрахований на ESM-runtime (Node ≥ 14.8 з ESM або Bun).
87
-
88
- ## Потік виконання / Використання
89
-
90
- ### Сценарій 1. Library mode (виклик з оркестратора)
10
+ ## Огляд
91
11
 
92
- 1. Зовнішній runner (`npx @nitra/cursor fix`) імпортує `run` з цього файлу.
93
- 2. Передає підготовлений `ctx` (зазвичай зі спільним `walkCache`, аби не повторювати обхід файлової системи між правилами).
94
- 3. `run(ctx)` повертає `runStandardRule(import.meta.dirname, ctx)`.
95
- 4. `runStandardRule`:
96
- - читає `meta.json` поточної теки правила,
97
- - виконує `applies` → JS-concerns → policy → mdc-refs (стандартний пайплайн "стандартного" правила),
98
- - повертає `0`/`1`.
99
- 5. Runner агрегує exit-коди всіх правил і вирішує загальний статус.
12
+ Файл запускає визначене правило. Приймає контекст прогону, виконує пропуск через `runStandardRule` і повертає результат. Запуск через командний рядок виконує повний еквівалент команди `npx @nitra/cursor fix <id>` і встановлює код виходу процесу на результат `runRuleCli`.
100
13
 
101
- ### Сценарій 2. Standalone mode
14
+ ## Поведінка
102
15
 
103
- 1. Користувач/CI запускає:
104
- ```bash
105
- bun npm/rules/js-bun-redis/fix.mjs
106
- ```
107
- 2. Module-evaluation сягає блоку `if (isRunAsCli(import.meta.url))` — умова `true`.
108
- 3. Виконується `await runRuleCli(import.meta.dirname)`:
109
- - завантаження конфігу,
110
- - whitelist,
111
- - повний CLI-пайплайн (включно з summary),
112
- - повертає числовий exit-code.
113
- 4. `process.exit(<code>)` завершує процес із цим кодом — CI/IDE бачить fail (`1`) або success (`0`).
16
+ 1. Запуск правила.
17
+ * Приймає контекст прогону.
18
+ * Виконує пропуск через runStandardRule.
19
+ * Повертає результат прогону.
20
+ 2. Запуск у режимі CLI.
21
+ * Виконується при запуску через CLI.
22
+ * Виконує повний еквівалент `npx @nitra/cursor fix <id>`.
23
+ * Встановлює код виходу процесу на результат runRuleCli.
114
24
 
115
- ### Чому два режими в одному файлі
25
+ ## Публічний API
116
26
 
117
- Це уніфікована конвенція системи правил `@nitra/cursor`: кожен `fix.mjs` є **і** імпортованим модулем (для оркестрованого прогону), **і** виконуваним скриптом (для локальної відладки конкретного правила). Завдяки `isRunAsCli` обидва шляхи безпечно співіснують: при імпорті side-effect-блок не спрацьовує.
27
+ run запускає правило: applies JS-concerns policy mdc-refs (через runStandardRule).
28
+ Library mode — викликається CLI orchestration через `import + run`.
118
29
 
119
- ### Типові команди
30
+ ## Гарантії поведінки
120
31
 
121
- - Прогнати лише це правило локально: `bun npm/rules/js-bun-redis/fix.mjs`.
122
- - Прогнати в межах усього набору правил: `npx @nitra/cursor fix` (runner викличе саме `run(ctx)`).
123
- - Прогнати з конкретним id через CLI: `npx @nitra/cursor fix js-bun-redis` (виконує по суті те саме, що й standalone-режим цього файлу).
32
+ - Read-only: файл не виконує операцій запису у файлову систему.
33
+ - Кешує результати в межах одного прогону.
34
+ - Не звертається до мережі.