@nitra/cursor 5.3.4 → 6.0.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 (173) 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 +21 -0
  4. package/bin/n-cursor.js +47 -24
  5. package/lib/docs/models.md +29 -18
  6. package/lib/docs/omlx-trace.md +51 -0
  7. package/lib/docs/omlx.md +31 -15
  8. package/lib/omlx.mjs +2 -5
  9. package/package.json +1 -1
  10. package/rules/abie/docs/fix.md +17 -11
  11. package/rules/adr/docs/fix.md +25 -140
  12. package/rules/bun/docs/fix.md +18 -151
  13. package/rules/capacitor/docs/fix.md +16 -13
  14. package/rules/capacitor/js/docs/platforms.md +31 -43
  15. package/rules/changelog/docs/fix.md +25 -169
  16. package/rules/ci4/docs/fix.md +11 -14
  17. package/rules/doc-files/doc-files.mdc +60 -0
  18. package/rules/doc-files/docs/fix.md +31 -0
  19. package/rules/doc-files/fix.mjs +19 -0
  20. package/{skills → rules}/doc-files/js/docgen-extract.mjs +42 -19
  21. package/{skills → rules}/doc-files/js/docgen-files-batch.mjs +18 -5
  22. package/{skills → rules}/doc-files/js/docgen-gen.mjs +46 -5
  23. package/{skills → rules}/doc-files/js/docgen-ignore.mjs +2 -1
  24. package/{skills → rules}/doc-files/js/docgen-scan.mjs +11 -3
  25. package/{skills → rules}/doc-files/js/docs/docgen-crc.md +1 -1
  26. package/{skills → rules}/doc-files/js/docs/docgen-extract-anchors.md +1 -1
  27. package/{skills → rules}/doc-files/js/docs/docgen-extract.md +2 -2
  28. package/{skills → rules}/doc-files/js/docs/docgen-files-batch.md +2 -2
  29. package/{skills → rules}/doc-files/js/docs/docgen-gen.md +2 -2
  30. package/{skills → rules}/doc-files/js/docs/docgen-ignore.md +4 -4
  31. package/rules/doc-files/js/docs/docgen-prompts.md +39 -0
  32. package/rules/doc-files/js/docs/docgen-scan.md +54 -0
  33. package/rules/doc-files/js/docs/lint.md +36 -0
  34. package/rules/doc-files/js/docs/units-js.md +31 -0
  35. package/rules/doc-files/js/docs/units-rs.md +35 -0
  36. package/rules/doc-files/js/docs/units.md +30 -0
  37. package/rules/doc-files/js/lint.mjs +96 -0
  38. package/{skills → rules}/doc-files/js/units-rs.mjs +37 -17
  39. package/rules/doc-files/lint/docs/lint.md +37 -0
  40. package/rules/doc-files/lint/lint.mjs +105 -0
  41. package/rules/doc-files/meta.json +1 -0
  42. package/rules/docker/docs/fix.md +21 -161
  43. package/rules/efes/docs/fix.md +23 -194
  44. package/rules/feedback/docs/fix.md +10 -8
  45. package/rules/ga/docs/fix.md +10 -5
  46. package/rules/ga/meta.json +1 -1
  47. package/rules/graphql/docs/fix.md +23 -119
  48. package/rules/hasura/docs/fix.md +19 -5
  49. package/rules/hasura/js/docs/internal_urls.md +34 -307
  50. package/rules/image-avif/docs/fix.md +16 -127
  51. package/rules/image-compress/docs/fix.md +20 -141
  52. package/rules/image-compress/js/docs/package_setup.md +22 -182
  53. package/rules/js-bun-db/docs/fix.md +23 -139
  54. package/rules/js-bun-db/js/docs/safety.md +33 -221
  55. package/rules/js-bun-redis/docs/fix.md +25 -114
  56. package/rules/js-bun-redis/js/docs/imports.md +18 -166
  57. package/rules/js-lint/docs/fix.md +30 -108
  58. package/rules/js-lint/js/docs/lint-findings.md +37 -17
  59. package/rules/js-lint/js/docs/lint.md +22 -238
  60. package/rules/js-lint/js/docs/tooling.md +34 -331
  61. package/rules/js-lint/js/lint.mjs +19 -12
  62. package/rules/js-lint/js-lint.mdc +1 -1
  63. package/rules/js-lint/meta.json +1 -1
  64. package/rules/js-lint-ci/docs/fix.md +16 -149
  65. package/rules/js-lint-ci/js/docs/lint.md +16 -136
  66. package/rules/js-lint-ci/js-lint-ci.mdc +1 -1
  67. package/rules/js-lint-ci/meta.json +1 -1
  68. package/rules/js-mssql/docs/fix.md +18 -123
  69. package/rules/js-mssql/js/docs/deps.md +28 -251
  70. package/rules/js-run/docs/fix.md +23 -138
  71. package/rules/js-run/js/docs/runtime.md +24 -378
  72. package/rules/k8s/docs/fix.md +18 -123
  73. package/rules/nginx-default-tpl/docs/fix.md +22 -118
  74. package/rules/nginx-default-tpl/js/docs/template.md +38 -360
  75. package/rules/npm-module/docs/fix.md +27 -89
  76. package/rules/npm-module/js/docs/header_doc_pointer.md +15 -15
  77. package/rules/npm-module/js/docs/package_structure.md +36 -258
  78. package/rules/npm-module/js/docs/rule_meta.md +25 -127
  79. package/rules/npm-module/js/docs/skill_meta.md +18 -180
  80. package/rules/npm-module/js/rule_meta.mjs +3 -3
  81. package/rules/php/docs/fix.md +21 -98
  82. package/rules/php/js/docs/tooling.md +20 -143
  83. package/rules/python/docs/fix.md +25 -157
  84. package/rules/python/js/docs/applies.md +20 -98
  85. package/rules/python/js/docs/tooling.md +27 -144
  86. package/rules/rego/docs/fix.md +24 -112
  87. package/rules/rego/js/docs/applies.md +20 -164
  88. package/rules/rego/js/docs/lint.md +15 -110
  89. package/rules/rego/meta.json +1 -1
  90. package/rules/release/docs/fix.md +16 -114
  91. package/rules/rust/docs/fix.md +24 -119
  92. package/rules/rust/js/docs/applies.md +20 -129
  93. package/rules/security/docs/fix.md +21 -78
  94. package/rules/security/js/docs/sample_secret.md +23 -182
  95. package/rules/security/js/docs/trufflehog.md +19 -128
  96. package/rules/security/meta.json +1 -1
  97. package/rules/style-lint/docs/fix.md +16 -150
  98. package/rules/style-lint/js/docs/lint.md +21 -172
  99. package/rules/style-lint/js/docs/tooling.md +19 -184
  100. package/rules/style-lint/js/lint.mjs +4 -3
  101. package/rules/style-lint/meta.json +1 -1
  102. package/rules/tauri/docs/fix.md +26 -152
  103. package/rules/tauri/js/docs/cargo_mutants_config.md +21 -159
  104. package/rules/tauri/js/docs/tooling.md +20 -217
  105. package/rules/test/docs/fix.md +19 -127
  106. package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +15 -127
  107. package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +17 -153
  108. package/rules/test/js/docs/cargo_mutants_config.md +24 -164
  109. package/rules/test/js/docs/location.md +24 -126
  110. package/rules/test/js/docs/no-process-chdir.md +20 -151
  111. package/rules/test/js/docs/no-relative-fs-path.md +24 -261
  112. package/rules/test/js/docs/stryker_config.md +48 -148
  113. package/rules/test/js/docs/vitest-config-pool-forks.md +21 -164
  114. package/rules/text/docs/fix.md +25 -113
  115. package/rules/text/js/docs/forbidden-prettier.md +21 -132
  116. package/rules/text/js/docs/formatting.md +60 -251
  117. package/rules/text/js/docs/lint.md +17 -114
  118. package/rules/text/js/lint.mjs +5 -3
  119. package/rules/text/lint/docs/lint.md +1 -1
  120. package/rules/text/lint/docs/run-dotenv-linter.md +1 -1
  121. package/rules/text/lint/docs/run-shellcheck.md +1 -1
  122. package/rules/text/lint/lint.mjs +13 -9
  123. package/rules/text/lint/run-dotenv-linter.mjs +13 -10
  124. package/rules/text/lint/run-shellcheck.mjs +10 -6
  125. package/rules/text/meta.json +1 -1
  126. package/rules/vue/docs/fix.md +25 -118
  127. package/rules/vue/js/docs/packages.md +25 -323
  128. package/rules/worktree/docs/fix.md +31 -150
  129. package/scripts/coverage-classify/docs/index.md +23 -209
  130. package/scripts/coverage-classify/docs/verdict-schema.md +14 -159
  131. package/scripts/dispatcher/docs/trace.md +35 -0
  132. package/scripts/docs/auto-rules.md +37 -361
  133. package/scripts/docs/lint-cli.md +12 -13
  134. package/scripts/docs/post-tool-use-fix.md +16 -15
  135. package/scripts/docs/skills-cli.md +26 -23
  136. package/scripts/docs/sync-claude-config.md +94 -34
  137. package/scripts/docs/worktree-cli.md +11 -34
  138. package/scripts/lib/docs/assert-project-root.md +14 -16
  139. package/scripts/lib/docs/changed-files.md +24 -139
  140. package/scripts/lib/docs/discover-check-rules-from-cursor.md +14 -146
  141. package/scripts/lib/docs/rule-meta.md +1 -1
  142. package/scripts/lib/docs/rule-predicates.md +20 -17
  143. package/scripts/lib/docs/run-rule-cli.md +14 -18
  144. package/scripts/lib/docs/run-rule.md +13 -20
  145. package/scripts/lib/docs/run-standard-rule.md +12 -15
  146. package/scripts/lib/docs/sync-gitignore-worktree.md +15 -18
  147. package/scripts/lib/rule-meta.mjs +10 -6
  148. package/scripts/lib/rule-predicates.mjs +1 -1
  149. package/scripts/lint-cli.mjs +28 -20
  150. package/scripts/sync-claude-config.mjs +4 -1
  151. package/scripts/utils/docs/with-lock.md +19 -12
  152. package/scripts/utils/with-lock.mjs +4 -2
  153. package/skills/doc-aggregate/SKILL.md +2 -2
  154. package/skills/doc-aggregate/js/docgen-ignore.mjs +6 -6
  155. package/skills/doc-aggregate/js/docs/docgen-ignore.md +1 -1
  156. package/skills/doc-aggregate/js/docs/docgen-scan.md +78 -0
  157. package/skills/doc-files/.changes/260612-0031.md +5 -0
  158. package/skills/doc-files/.changes/260612-0036.md +5 -0
  159. package/skills/doc-files/.changes/260612-0114.md +5 -0
  160. package/skills/doc-files/SKILL.md +6 -6
  161. package/skills/fix/js/docs/llm-worker.md +17 -15
  162. package/skills/fix/js/docs/orchestrator.md +30 -23
  163. package/skills/fix/js/docs/t0.md +26 -16
  164. package/skills/start-check/js/docs/check.md +26 -22
  165. package/skills/taze/js/docs/diff.md +44 -20
  166. package/skills/doc-files/js/docs/docgen-prompts.md +0 -32
  167. package/skills/doc-files/js/docs/docgen-scan.md +0 -25
  168. package/skills/doc-files/js/docs/units-rs.md +0 -35
  169. /package/{skills → rules}/doc-files/js/docgen-crc.mjs +0 -0
  170. /package/{skills → rules}/doc-files/js/docgen-extract-anchors.mjs +0 -0
  171. /package/{skills → rules}/doc-files/js/docgen-prompts.mjs +0 -0
  172. /package/{skills → rules}/doc-files/js/units-js.mjs +0 -0
  173. /package/{skills → rules}/doc-files/js/units.mjs +0 -0
@@ -1 +1 @@
1
- { "auto": { "glob": ".github/workflows/**" }, "lint": "ci" }
1
+ { "auto": { "glob": ".github/workflows/**" }, "lint": "full" }
@@ -1,135 +1,39 @@
1
1
  ---
2
2
  docgen:
3
3
  source: npm/rules/graphql/fix.mjs
4
- crc: 12fc1644
4
+ crc: 38cf876b
5
+ score: 100
5
6
  ---
6
7
 
7
- # `npm/rules/graphql/fix.mjs`
8
+ # fix.mjs
8
9
 
9
10
  ## Огляд
10
11
 
11
- Файл є точкою входу до правила `graphql` у складі CLI-інструмента `@nitra/cursor`. Він поєднує дві ролі:
12
+ Виконує обробку JS-занепокоєних та політики на вхідному контексті прогону, генеруючи посилання MDC та повертаючи результат.
12
13
 
13
- 1. **Library mode** експортує функцію `run(ctx)`, яку зовнішня CLI-оркестрація викликає через `import + run(ctx)` як частину пакетного прогону всіх правил.
14
- 2. **Standalone mode** — якщо файл запущено напряму (`bun rules/graphql/fix.mjs`), виконується повний еквівалент команди `npx @nitra/cursor fix graphql` із завантаженням конфігурації, whitelist та підсумком (summary).
14
+ Виконується як автономний скрипт для виконання повного еквіваленту команди `npx @nitra/cursor fix <id>` та перевірки результату прогону.
15
15
 
16
- Сама логіка перевірки винесена у спільний helper `runStandardRule`, тобто `fix.mjs` для правила `graphql` — це тонкий wrapper, який лише прив'язує спільну механіку до конкретної директорії правила (через `import.meta.dirname`). Послідовність перевірки, що виконується в результаті: `applies → JS-concerns → policy → mdc-refs`.
16
+ ## Поведінка
17
17
 
18
- Файл є частиною стандартизованої конвенції правил `npm/rules/<id>/fix.mjs`, де `<id>` — ідентифікатор правила (тут `graphql`).
18
+ 1. Запуск правила.
19
+ * Приймає контекст прогону.
20
+ * Виконує застосування JS-занепокоєних.
21
+ * Застосовує політику.
22
+ * Генерує посилання MDC.
23
+ * Повертає результат прогону.
19
24
 
20
- ## Експорти / API
25
+ 2. Запуск у режимі CLI.
26
+ * Виконується як автономний скрипт.
27
+ * Виконує повний еквівалент команди `npx @nitra/cursor fix <id>`.
28
+ * Перевіряє результат прогону для встановлення коду виходу.
21
29
 
22
- | Експорт | Тип | Призначення |
23
- | ------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------- |
24
- | `run` | `function(ctx?): Promise<number>` | Named export — library entry-point правила. Викликається оркестратором, який пакетно запускає набір правил. |
30
+ ## Публічний API
25
31
 
26
- Default export відсутній. Інших named-експортів файл не визначає.
32
+ run запускає правило: applies JS-concerns → policy → mdc-refs (через runStandardRule).
33
+ Library mode — викликається CLI orchestration через `import + run`.
27
34
 
28
- Окремий top-level `if`-блок наприкінці файла активує standalone-режим — він не є експортом, а виконується як side-effect модуля при прямому запуску.
35
+ ## Гарантії поведінки
29
36
 
30
- ## Функції
31
-
32
- ### `run(ctx)`
33
-
34
- ```js
35
- /**
36
- *
37
- */
38
- export function run(ctx) {
39
- return runStandardRule(import.meta.dirname, ctx)
40
- }
41
- ```
42
-
43
- **Призначення.** Library-обгортка над `runStandardRule`, що запускає стандартний пайплайн правила `graphql`: `applies → JS-concerns → policy → mdc-refs`. Конкретні фази (підбір файлів, перевірка JS, policy-правила, перевірка mdc-посилань) реалізовані у спільному helper; `fix.mjs` тільки повідомляє, _яке саме_ правило виконувати, — через шлях до своєї директорії (`import.meta.dirname`), де лежать `meta.json`, `*.mdc`, підтеки `js/`, `policy/`, `lib/` тощо.
44
-
45
- **Параметри.**
46
-
47
- | Параметр | Тип | Обов'язковий | Опис |
48
- | -------- | ----------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
49
- | `ctx` | `RuleContext` (з `../../scripts/lib/run-standard-rule.mjs`) | Ні | Контекст прогону. Передається оркестратором для перевикористання ресурсів між правилами (наприклад, `walkCache` — кеш обходу файлової системи, аби не сканувати дерево заново для кожного правила). Якщо `ctx` не передано, `runStandardRule` працює зі своїм дефолтним станом. |
50
-
51
- **Повертає.** `Promise<number>` — exit-code прогону правила:
52
-
53
- - `0` — правило пройшло без порушень (OK).
54
- - `1` — виявлено порушення (правило фейлиться).
55
-
56
- **Side effects.** Сам по собі `run` не має побічних ефектів у файлі — повертає `Promise`, отриманий від `runStandardRule`. Усі реальні ефекти (читання FS, друк діагностики у stdout/stderr, оновлення кешу в `ctx`) інкапсульовані в `runStandardRule`. Зокрема, у library-режимі функція **не** викликає `process.exit` — управління exit-кодом лежить на оркестраторі.
57
-
58
- ### Standalone-блок (top-level `if`)
59
-
60
- ```js
61
- if (isRunAsCli(import.meta.url)) {
62
- // eslint-disable-next-line n/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
63
- process.exit(await runRuleCli(import.meta.dirname))
64
- }
65
- ```
66
-
67
- Це не функція, а top-level side-effect модуля. Виконується одноразово при завантаженні.
68
-
69
- **Умова активації.** `isRunAsCli(import.meta.url)` повертає `true`, коли модуль завантажений як точка входу (тобто шлях файла збігається з тим, що передано Node/Bun у `process.argv`), а не імпортований як бібліотека.
70
-
71
- **Дія.** Викликає `runRuleCli(import.meta.dirname)` — повний CLI-флоу одного правила (config-loading, whitelist, summary) — і завершує процес його exit-кодом через `process.exit`. Це робить файл прямим аналогом виклику `npx @nitra/cursor fix graphql`.
72
-
73
- **Чому `process.exit` явний.** Standalone entry-point має повернути коректний exit-code для CI/IDE-інтеграції, тому два правила ESLint (`n/no-process-exit`, `unicorn/no-process-exit`) свідомо вимкнено для цього рядка коментарем-обґрунтуванням.
74
-
75
- **Чому `await` на top-level.** Файл використовує top-level `await` — це валідно для ESM-модулів. `runRuleCli` повертає `Promise<number>`, і його результат потрібен синхронно як аргумент `process.exit`.
76
-
77
- ## Залежності
78
-
79
- ### Внутрішні (відносні)
80
-
81
- | Модуль | Імпорт | Роль |
82
- | ----------------------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------- |
83
- | `../../scripts/lib/run-rule-cli.mjs` | `isRunAsCli`, `runRuleCli` | Інфраструктура standalone-режиму: визначення, чи файл запущено як CLI, та повний CLI-флоу одного правила. |
84
- | `../../scripts/lib/run-standard-rule.mjs` | `runStandardRule` | Стандартний пайплайн правила (`applies → JS-concerns → policy → mdc-refs`) і тип `RuleContext`. |
85
-
86
- Імпорти відносні, бо `fix.mjs` лежить у `npm/rules/graphql/`, а спільні helpers — у `npm/scripts/lib/`. Два рівні `..` піднімають із `rules/graphql/` до `npm/` і потім спускають у `scripts/lib/`.
87
-
88
- ### Зовнішні
89
-
90
- Прямих зовнішніх (npm) залежностей файл не оголошує. Будь-які зовнішні пакети підтягуються транзитивно через `runStandardRule` / `runRuleCli`.
91
-
92
- ### Платформенні / рантайм
93
-
94
- - **ES Modules** — файл використовує синтаксис ESM (`import`, `export`), top-level `await`, `import.meta.url`, `import.meta.dirname`.
95
- - **`import.meta.dirname`** — доступне у сучасних Node.js (>= 20.11) та Bun. Повертає абсолютний шлях до директорії модуля; використовується як ідентифікатор правила для helpers.
96
- - **`process.exit`** — Node.js/Bun API; завершує процес із заданим exit-кодом.
97
-
98
- ## Потік виконання / Використання
99
-
100
- ### Library mode (оркестрація)
101
-
102
- 1. Зовнішній код (CLI-оркестратор `@nitra/cursor`) робить `import { run } from '<...>/rules/graphql/fix.mjs'`.
103
- 2. Оркестратор готує `ctx` (наприклад, спільний `walkCache`) і викликає `await run(ctx)`.
104
- 3. `run` делегує виклик у `runStandardRule(import.meta.dirname, ctx)`. Helper, маючи шлях до директорії правила, читає її `meta.json`, `*.mdc`, підтеки `js/`, `policy/` і виконує стандартний пайплайн.
105
- 4. Повертається `0` або `1`. Оркестратор агрегує коди всіх правил у фінальний exit-status.
106
-
107
- У цьому режимі `process.exit` **не** викликається — модуль не завершує процес самостійно.
108
-
109
- ### Standalone mode (пряма CLI)
110
-
111
- 1. Користувач запускає `bun npm/rules/graphql/fix.mjs` (або шлях через рантайм).
112
- 2. ESM-модуль завантажується. Виконується `isRunAsCli(import.meta.url)` — повертає `true`.
113
- 3. Викликається `await runRuleCli(import.meta.dirname)` — повний CLI-флоу (config, whitelist, summary).
114
- 4. `process.exit(<code>)` завершує процес. Code приходить у CI/IDE як результат прогону правила.
115
-
116
- Цей режим повністю еквівалентний `npx @nitra/cursor fix graphql` і існує, щоб правило можна було запустити ізольовано — для дебагу або інтеграції з IDE-таском без участі оркестратора.
117
-
118
- ### Дві ролі в одному файлі
119
-
120
- Подвійна роль (library `run` + standalone `main`) дозволяє:
121
-
122
- - **Перевикористовувати** код пайплайна — і оркестратор, і пряма CLI йдуть через однакову логіку `runStandardRule` / `runRuleCli`.
123
- - **Дотримуватися конвенції** `npm/rules/<id>/fix.mjs`: усі правила мають однакову структуру entry-файла, тому інструменти (IDE-завдання, скрипти scaffold) можуть запускати будь-яке правило за єдиним шляхом.
124
-
125
- ### Розширення
126
-
127
- Щоб додати своєрідну поведінку правила `graphql`, не треба змінювати `fix.mjs` — достатньо покласти відповідні файли в директорію правила:
128
-
129
- - `meta.json` — метадані (id, опис).
130
- - `graphql.mdc` — людиночитна частина правила.
131
- - `js/` — JS-перевірки (фаза JS-concerns).
132
- - `policy/` — policy-перевірки.
133
- - `lib/` — спільний код правила.
134
-
135
- `runStandardRule` сам підбере й виконає те, що знайде в директорії. `fix.mjs` залишається тонким wrapper-ом.
37
+ - Read-only: файл не виконує операцій запису у файлову систему.
38
+ - Кешує результати в межах одного прогону.
39
+ - Не звертається до мережі.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  docgen:
3
3
  source: npm/rules/hasura/fix.mjs
4
- crc: 12fc1644
4
+ crc: 38cf876b
5
5
  score: 100
6
6
  ---
7
7
 
@@ -9,16 +9,30 @@ docgen:
9
9
 
10
10
  ## Огляд
11
11
 
12
- Цей файл ініціює застосування правил. Він запускає процес, що включає перевірку JS-занепокоєнь та політик. При самостійному запуску скрипт завантажує конфігурацію та вайтлістинг, а також надає звіт про виконання.
12
+ Виконує застосування політики JS-занепокоєних на наданому контексті прогону, генеруючи посилання на MDC та повертаючи результат.
13
+
14
+ Виконується при запуску через командний рядок, виконуючи повний еквівалент команди `npx @nitra/cursor fix <id>`, завантажуючи конфігурацію, перевіряючи дозволи, генеруючи підсумок та визначаючи код виходу.
13
15
 
14
16
  ## Поведінка
15
17
 
16
- 1. Викликати функцію `run` для виконання правила. Це ініціює процес застосування правил, включаючи перевірку JS-занепокоєнь, політик та посилань MDC.
17
- 2. Якщо скрипт виконується як окрема утиліта (standalone), викликати механізм оркестрації для виконання правила. Це забезпечує повну функціональність, включаючи завантаження конфігурації, вайтлістинг та підсумок.
18
+ 1. Запуск правила.
19
+ * Приймає контекст прогону.
20
+ * Виконує застосування JS-занепокоєних.
21
+ * Застосовує політику.
22
+ * Генерує посилання на MDC.
23
+ * Повертає результат прогону.
24
+ 2. Запуск правила у режимі CLI.
25
+ * Виконується при запуску через CLI.
26
+ * Виконує повний еквівалент команди `npx @nitra/cursor fix <id>`.
27
+ * Виконує завантаження конфігурації.
28
+ * Виконує перевірку дозволів.
29
+ * Генерує підсумок.
30
+ * Визначає код виходу.
18
31
 
19
32
  ## Публічний API
20
33
 
21
- run — виконує послідовність дій: застосовує правила, обробляє JavaScript-занепокоєння, перевіряє політику та посилання MDC.
34
+ run — запускає правило: applies JS-concerns policy mdc-refs (через runStandardRule).
35
+ Library mode — викликається CLI orchestration через `import + run`.
22
36
 
23
37
  ## Гарантії поведінки
24
38
 
@@ -1,326 +1,53 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/hasura/js/internal_urls.mjs
4
+ crc: 83abefa3
5
+ score: 90
6
+ ---
7
+
1
8
  # internal_urls.mjs
2
9
 
3
10
  ## Огляд
4
11
 
5
- Модуль `npm/rules/hasura/js/internal_urls.mjs` реалізує перевірку правила `hasura.mdc` для проєктів **nitra** та **abie**. Його єдина мета — гарантувати, що значення змінної середовища `HASURA_GRAPHQL_ENDPOINT`, заданої в будь-якому файлі `*.env` репозиторію, є **внутрішнім кластерним URL** (GKE/GCP DNS-суфікс `<cluster>.internal`), а не публічним доменом.
6
-
7
- Логіка активується лише за умови, що поле `repository` кореневого `package.json` вказує на одну з організацій:
8
-
9
- - `https://github.com/nitra/...`
10
- - `https://github.com/abinbevefes/...`
11
-
12
- Якщо ці маркери відсутні, перевірка пропускається без помилок (аналогічно до інших abie-перевірок).
13
-
14
- Очікуваний формат URL:
15
-
16
- ```
17
- http://<service>.<namespace>.svc.<cluster>.internal:<port>
18
- ```
19
-
20
- Приклад валідного значення:
21
-
22
- ```
23
- http://contract-h-hl.ua-contract.svc.abie-ua.internal:8080
24
- ```
25
-
26
- Сегменти `<service>` та `<namespace>` за наявності YAML-файлів `hasura/k8s/base/svc-hl.yaml` (поле `metadata.name`, headless-сервіс із суфіксом `-h-hl`) та `hasura/k8s/base/namespace.yaml` (поле `metadata.name`) додатково звіряються з фактичними значеннями kubernetes-маніфестів.
27
-
28
- Скануються всі файли, що відповідають масці `*.env` (наприклад, `dev.env`, `production.env`). Файл з іменем рівно `.env` (локальний файл розробника) **виключається** з перевірки. Не обходяться службові каталоги: `node_modules`, `.git`, `dist`, `coverage`, `.turbo`, `.next` (відповідно до конфігурації `walkDir`).
29
-
30
- ## Експорти / API
31
-
32
- Модуль є ES-модулем (`.mjs`) і експортує:
33
-
34
- | Експорт | Тип | Призначення |
35
- | ----------------------------- | --------------- | ------------------------------------------------------------------------------------------------- |
36
- | `parseInternalHasuraEndpoint` | функція | Розбирає URL-рядок на сегменти кластерної DNS-адреси (`service`, `namespace`, `cluster`, `port`). |
37
- | `isEnvFile` | функція | Чи підлягає файл за відносним шляхом перевірці hasura.mdc. |
38
- | `isNitraOrAbieRepository` | функція | Чи репозиторій належить організаціям nitra / abinbevefes. |
39
- | `check` | функція (async) | Точка входу: запускає повну перевірку для cwd, повертає exit-код процесу. |
40
-
41
- Внутрішні (не експортовані) допоміжні функції: `readYamlMetadataName`, `collectEnvFiles`, `checkEnvFile`, `readRootRepositoryUrl`.
42
-
43
- Внутрішні константи:
44
-
45
- | Константа | Значення | Призначення |
46
- | ----------------------------- | ----------------------------------- | ----------------------------------------------------------------------- |
47
- | `NITRA_REPOSITORY_URL_MARKER` | `'https://github.com/nitra/'` | Маркер репозиторіїв організації nitra. |
48
- | `ABIE_REPOSITORY_URL_MARKER` | `'https://github.com/abinbevefes/'` | Маркер репозиторіїв організації abinbevefes (abie). |
49
- | `HASURA_BASE_DIR` | `'hasura/k8s/base'` | Базовий каталог k8s-маніфестів Hasura. |
50
- | `HASURA_SVC_HL_FILE` | `'hasura/k8s/base/svc-hl.yaml'` | Шлях до headless-сервіса. |
51
- | `HASURA_NAMESPACE_FILE` | `'hasura/k8s/base/namespace.yaml'` | Шлях до namespace-маніфесту. |
52
- | `ENV_FILE_RE` | `/\.env$/u` | Регулярка-маркер `*.env` файлів. |
53
- | `HASURA_ENDPOINT_LINE_RE` | (див. нижче) | Регулярка для знаходження рядка `HASURA_GRAPHQL_ENDPOINT=...` у `.env`. |
54
- | `INTERNAL_HASURA_URL_RE` | (див. нижче) | Регулярка валідації внутрішнього кластерного URL. |
55
- | `INTERNAL_DNS_SUFFIX` | `'.internal'` | DNS-суфікс GKE/GCP-кластера. |
56
-
57
- Регулярні вирази:
58
-
59
- - `HASURA_ENDPOINT_LINE_RE = /^[ \t]*(?:export[ \t]+)?HASURA_GRAPHQL_ENDPOINT[ \t]*=[ \t]*['"]?([^'"\r\n#]+)/mu`
60
- - Multiline, Unicode. Підтримує `export ` префікс, табуляції/пробіли навколо `=`, опційне обрамлення лапками (`'` або `"`). Капчурить значення до символа лапки, перенесення рядка або `#` (коментар).
61
- - `INTERNAL_HASURA_URL_RE = /^http:\/\/([^./]+)\.([^./]+)\.svc\.([^./:]+\.internal):(\d+)\/?$/u`
62
- - Дозволяє лише схему `http://` (TLS усередині кластера зайвий).
63
- - Капчурить чотири сегменти: `service`, `namespace`, DNS-суфікс (з обов'язковим `.internal`), `port`.
64
- - Допускає необов'язковий завершальний слеш.
65
-
66
- ## Функції
67
-
68
- ### `parseInternalHasuraEndpoint(url)`
69
-
70
- **Сигнатура:**
71
-
72
- ```js
73
- export function parseInternalHasuraEndpoint(url)
74
- ```
75
-
76
- **Параметри:**
77
-
78
- - `url` (`string`) — значення `HASURA_GRAPHQL_ENDPOINT`, попередньо очищене від обрамляючих лапок (для надійності функція ще раз застосовує `.trim()`).
79
-
80
- **Повертає:**
81
-
82
- - При успіху: `{ ok: true, service: string, namespace: string, cluster: string, port: string }`. Поле `cluster` містить ім'я кластера **без** суфіксу `.internal` (наприклад, `abie-ua`).
83
- - При невідповідності формату: `{ ok: false }`.
84
-
85
- **Поведінка та особливості:**
86
-
87
- - Дозволяє виключно протокол `http://` і DNS-суфікс `<cluster>.internal` (GKE/GCP-конвенція).
88
- - Усі сегменти повертаються як рядки (включно з `port`, попри те що значення цифрове).
89
- - Side effects відсутні.
90
-
91
- ### `readYamlMetadataName(absPath, kind)` (внутрішня)
92
-
93
- **Сигнатура:**
94
-
95
- ```js
96
- async function readYamlMetadataName(absPath, kind)
97
- ```
98
-
99
- **Параметри:**
100
-
101
- - `absPath` (`string`) — абсолютний шлях до YAML-файла.
102
- - `kind` (`string`) — очікуваний `kind` ресурсу (`'Service'`, `'Namespace'` тощо).
103
-
104
- **Повертає:** `Promise<string | null>` — значення `metadata.name` першого документа з відповідним `kind`, або `null`, якщо:
105
-
106
- - файл не існує;
107
- - парсинг YAML не вдався (`parseAllDocuments` кинув виключення);
108
- - жоден документ у файлі не має заданого `kind` або не має `metadata.name`.
109
-
110
- **Side effects:** одне читання з файлової системи (`readFile`); жодних винятків назовні не пропускає.
111
-
112
- ### `isEnvFile(relPath)`
113
-
114
- **Сигнатура:**
115
-
116
- ```js
117
- export function isEnvFile(relPath)
118
- ```
119
-
120
- **Параметри:**
121
-
122
- - `relPath` (`string`) — posix-шлях файла відносно кореня репозиторію.
123
-
124
- **Повертає:** `boolean`.
125
-
126
- - `true` — для файлів, у яких є ім'я перед `.env`: `dev.env`, `nitra.env`, `production.env`.
127
- - `false` — для всіх інших, **зокрема** для файла рівно `.env` без імені (локальний файл розробника, виключений з правила hasura.mdc).
128
-
129
- **Side effects:** немає.
130
-
131
- ### `collectEnvFiles(root, ignorePaths)` (внутрішня)
132
-
133
- **Сигнатура:**
134
-
135
- ```js
136
- async function collectEnvFiles(root, ignorePaths)
137
- ```
138
-
139
- **Параметри:**
140
-
141
- - `root` (`string`) — абсолютний шлях кореня репозиторію.
142
- - `ignorePaths` (`string[]`) — абсолютні шляхи каталогів, які слід повністю пропустити при обході (зчитуються з cursor-конфігу).
143
-
144
- **Повертає:** `Promise<string[]>` — відсортовані за `localeCompare` posix-шляхи `*.env` файлів відносно `root`.
145
-
146
- **Поведінка:**
147
-
148
- - Використовує `walkDir` з callback-фільтром.
149
- - Конвертує windows-роздільники `\` у posix-роздільники `/` перед перевіркою `isEnvFile`.
150
- - Працює дитерміновано завдяки сортуванню `toSorted`.
151
-
152
- **Side effects:** обхід файлової системи.
153
-
154
- ### `checkEnvFile(relPath, cwd, expected, reporter)` (внутрішня)
155
-
156
- **Сигнатура:**
157
-
158
- ```js
159
- async function checkEnvFile(relPath, cwd, expected, reporter)
160
- ```
161
-
162
- **Параметри:**
163
-
164
- - `relPath` (`string`) — відносний posix-шлях файла (для повідомлень репортера).
165
- - `cwd` (`string`) — корінь репозиторію (для побудови абсолютного шляху).
166
- - `expected` (`{ service: string | null, namespace: string | null }`) — очікувані сегменти, прочитані з YAML-маніфестів; `null`-поля пропускаються.
167
- - `reporter` (`{ pass: (msg: string) => void, fail: (msg: string) => void }`) — обробник результатів (зазвичай з `createCheckReporter`).
168
-
169
- **Повертає:** `Promise<void>`. Результат комунікується через `reporter`.
170
-
171
- **Поведінка по гілках:**
172
-
173
- 1. Якщо в файлі **немає** змінної `HASURA_GRAPHQL_ENDPOINT` — функція мовчки виходить без виклику `pass`/`fail`.
174
- 2. Якщо значення не парситься як внутрішній кластерний URL — викликає `fail` з прикладом очікуваного формату (`https://<service>.<namespace>.svc.<cluster>.internal:<port>`).
175
- 3. Якщо `expected.service` задане і не збігається — `fail` з посиланням на `hasura/k8s/base/svc-hl.yaml`.
176
- 4. Якщо `expected.namespace` задане і не збігається — `fail` з посиланням на `hasura/k8s/base/namespace.yaml`.
177
- 5. Інакше — `pass` з підтвердженням, що URL внутрішній кластерний.
178
-
179
- **Side effects:** читання файла, виклики методів `reporter`.
180
-
181
- **Примітка:** в `fail`-повідомленні приклад наведений зі схемою `https://`, хоча сама регулярка `INTERNAL_HASURA_URL_RE` дозволяє лише `http://` (так задумано — TLS усередині кластера зайвий).
182
-
183
- ### `readRootRepositoryUrl(cwd)` (внутрішня)
184
-
185
- **Сигнатура:**
186
-
187
- ```js
188
- async function readRootRepositoryUrl(cwd)
189
- ```
190
-
191
- **Параметри:**
192
-
193
- - `cwd` (`string`) — корінь репозиторію.
194
-
195
- **Повертає:** `Promise<string | null>` — URL з поля `repository` (нормалізований через `getRepositoryUrl`) або `null`, якщо:
196
-
197
- - `package.json` не існує;
198
- - JSON не валідний;
199
- - поле `repository` відсутнє / нерозпізнаний формат.
200
-
201
- **Side effects:** одне читання `package.json`.
202
-
203
- ### `isNitraOrAbieRepository(url)`
204
-
205
- **Сигнатура:**
206
-
207
- ```js
208
- export function isNitraOrAbieRepository(url)
209
- ```
210
-
211
- **Параметри:**
212
-
213
- - `url` (`string | null | undefined`) — URL репозиторію.
214
-
215
- **Повертає:** `boolean`.
216
-
217
- - `true`, якщо `url` — рядок і містить (case-insensitive) маркер `https://github.com/nitra/` або `https://github.com/abinbevefes/`.
218
- - `false` — у решті випадків (включно з `null`, `undefined`, не-рядковими значеннями).
219
-
220
- **Side effects:** немає.
221
-
222
- ### `check(cwd?)`
223
-
224
- **Сигнатура:**
225
-
226
- ```js
227
- export async function check(cwd = process.cwd())
228
- ```
229
-
230
- **Параметри:**
231
-
232
- - `cwd` (`string`, опційний, за замовчуванням `process.cwd()`) — корінь репозиторію.
233
-
234
- **Повертає:** `Promise<number>` — exit-код процесу (`0` — OK або правило не застосовується, `1` — є хоча б одне порушення). Конкретне значення формує `reporter.getExitCode()`.
235
-
236
- **Поведінка (послідовно):**
237
-
238
- 1. Створює репортер через `createCheckReporter()`.
239
- 2. Зчитує URL репозиторію з `package.json`. Якщо це не nitra/abie — `pass('Пропущено: …')` і повертає exit-код (зазвичай `0`).
240
- 3. Зчитує очікувані `service` і `namespace` з YAML-маніфестів (обидва можуть бути `null`).
241
- 4. Завантажує `ignorePaths` з cursor-конфігу (`loadCursorIgnorePaths`).
242
- 5. Збирає всі `*.env` файли. Якщо їх немає — `pass('Не знайдено жодного *.env файла — нічого перевіряти')` і повертає exit-код.
243
- 6. Послідовно (без паралелізму) викликає `checkEnvFile` для кожного знайденого файла.
244
- 7. Якщо після перевірок exit-код залишився `0` і **жоден** файл не мав `HASURA_GRAPHQL_ENDPOINT` (тобто не було ні `pass`, ні `fail` зі змістом перевірки), додає підсумкове `pass` з кількістю та іменами перевірених файлів.
245
-
246
- **Side effects:** читання файлів, обхід каталогів, виведення повідомлень репортера (зазвичай у stdout/stderr).
247
-
248
- ## Залежності
249
-
250
- ### Зовнішні модулі (npm)
251
-
252
- - `yaml` — функція `parseAllDocuments` для парсингу мульти-документних YAML-файлів kubernetes-маніфестів.
253
-
254
- ### Node.js core
255
-
256
- - `node:fs` — `existsSync` для синхронної перевірки наявності `package.json` та YAML-файлів.
257
- - `node:fs/promises` — `readFile` для асинхронного читання файлів у UTF-8.
258
- - `node:path` — `basename`, `join`, `relative` для роботи зі шляхами.
259
-
260
- ### Внутрішні модулі репозиторію
261
-
262
- - `../../../scripts/auto-rules.mjs` — `getRepositoryUrl` для нормалізації поля `repository` у `package.json` (підтримує і рядкову, і об'єктну форму).
263
- - `../../../scripts/lib/check-reporter.mjs` — `createCheckReporter` для уніфікованого механізму репортингу `pass`/`fail` та обчислення exit-коду.
264
- - `../../../scripts/lib/load-cursor-config.mjs` — `loadCursorIgnorePaths` для отримання списку каталогів, виключених з обходу (повертає абсолютні шляхи).
265
- - `../../../scripts/utils/walkDir.mjs` — `walkDir` для рекурсивного обходу файлової системи з callback-логікою і набором default-ignore (`node_modules`, `.git`, `dist`, `coverage`, `.turbo`, `.next`).
266
-
267
- ### Файли, що читаються в рантаймі
268
-
269
- - `<cwd>/package.json` — джерело поля `repository`.
270
- - `<cwd>/hasura/k8s/base/svc-hl.yaml` — джерело очікуваного `service` (якщо існує).
271
- - `<cwd>/hasura/k8s/base/namespace.yaml` — джерело очікуваного `namespace` (якщо існує).
272
- - `<cwd>/**/*.env` (без рівно `.env` і без ignore-каталогів) — файли, що перевіряються.
273
-
274
- ## Потік виконання / Використання
12
+ parseInternalHasuraEndpoint
13
+ Витягує значення HASURA_GRAPHQL_ENDPOINT з конфігурації для формування внутрішнього кластерного URL
275
14
 
276
- ### Сценарій 1. Запуск як check-функції правила hasura.mdc
15
+ isEnvFile
16
+ Перевіряє, чи файл має розширення .env і не є локальним файлом розробника
277
17
 
278
- Модуль очікувано викликається з єдиної точки входу `check()` через інфраструктуру `npm/rules`/`scripts`. Типове використання:
18
+ isNitraOrAbieRepository
19
+ Перевіряє, чи URL репозиторію містить маркери nitra або abie
279
20
 
280
- ```js
281
- import { check } from './internal_urls.mjs'
21
+ check
22
+ Перевіряє коректність HASURA_GRAPHQL_ENDPOINT у файлах .env відповідно до конфігурації з package.json та YAML файлів
282
23
 
283
- const exitCode = await check(process.cwd())
284
- process.exitCode = exitCode
285
- ```
24
+ ## Поведінка
286
25
 
287
- ### Сценарій 2. Послідовність кроків при виконанні `check()`
26
+ parseInternalHasuraEndpoint
27
+ Розбирає значення HASURA_GRAPHQL_ENDPOINT як внутрішній кластерний URL
288
28
 
289
- 1. **Препроцесинг репозиторію.** Зчитується `package.json`. Якщо `repository` не вказує на nitra/abie — правило мовчки пропускається з повідомленням `pass`.
290
- 2. **Підготовка очікуваних значень.** Зчитуються `metadata.name` з `svc-hl.yaml` (як `Service`) і `namespace.yaml` (як `Namespace`). Кожне поле може бути `null` (тоді відповідна перевірка для сегмента URL не виконується).
291
- 3. **Збір кандидатів.** Через `walkDir` з ignore-списком з cursor-конфігу збираються усі `*.env` файли (відсортовано). Якщо колекція порожня — повідомляється `pass` і завершується.
292
- 4. **Перевірка кожного файла.** Для кожного знайденого `*.env`:
293
- - Якщо у файлі немає `HASURA_GRAPHQL_ENDPOINT` — пропуск без репортингу.
294
- - Інакше значення розбирається `parseInternalHasuraEndpoint`. Якщо парсинг не вдався — `fail`.
295
- - Якщо `expected.service` заданий і `parsed.service` не збігається — `fail`.
296
- - Якщо `expected.namespace` заданий і `parsed.namespace` не збігається — `fail`.
297
- - Інакше — `pass`.
298
- 5. **Підсумок.** Якщо за результатом усіх перевірок exit-код залишився `0` (тобто жодного `fail` не було), додається підсумкове `pass` з переліком імен файлів. Це покриває кейс, коли всі `*.env` не містили змінної взагалі.
299
- 6. **Exit-код.** Повертається через `reporter.getExitCode()`: `0` — успіх, `1` — є порушення.
29
+ isEnvFile
30
+ Перевіряє, чи файл має розширення .env і не є локальним файлом розробника
300
31
 
301
- ### Сценарій 3. Що вважається валідним URL
32
+ isNitraOrAbieRepository
33
+ Перевіряє, чи URL репозиторію містить маркери nitra або abie
302
34
 
303
- Валідні приклади:
35
+ check
36
+ Перевіряє коректність HASURA_GRAPHQL_ENDPOINT у файлах .env відповідно до конфігурації з package.json та YAML файлів
304
37
 
305
- - `http://contract-h-hl.ua-contract.svc.abie-ua.internal:8080`
306
- - `http://hasura-h-hl.nitra-prod.svc.nitra-cluster.internal:8080/`
38
+ ## Публічний API
307
39
 
308
- Невалідні приклади (викличуть `fail`):
40
+ parseInternalHasuraEndpoint розбиває значення `HASURA_GRAPHQL_ENDPOINT` на внутрішній URL кластера. Дозволяє `http://` та DNS-суфікс `<cluster>.internal` (GKE/GCP). Поле `cluster` містить ім'я кластера без `.internal` (наприклад `abie-ua`). Повертає сегменти або `{ ok: false }` при невідповідності формату внутрішнього кластерного URL.
309
41
 
310
- - `https://my.public.domain:443` публічний домен.
311
- - `http://hasura-h-hl.nitra-prod.svc.cluster.local:8080` — DNS-суфікс `.local`, а не `.internal`.
312
- - `http://hasura-h-hl.svc.abie-ua.internal:8080` — відсутній сегмент `namespace`.
313
- - `http://hasura-h-hl.nitra-prod.svc.abie-ua.internal` — відсутній port.
314
- - `http://hasura-h-hl.nitra-prod.svc.abie-ua.internal:8080/graphql` — є шлях після `/`.
42
+ isEnvFile — визначає, чи відносний шлях закінчується на `*.env`, який необхідно перевіряти (hasura.mdc). Файл з іменем `.env` повертається як виняток (false).
315
43
 
316
- ### Сценарій 4. Інтеграція в репортинг
44
+ isNitraOrAbieRepository перевіряє, чи URL репозиторію вказує на `nitra` або `abie` (за маркерами hasura.mdc).
317
45
 
318
- Для цілісного запуску модуль не виводить нічого сам усі повідомлення (`pass`/`fail`) делегуються `createCheckReporter()`. Це означає, що формат логів, кольори та сумарний exit-код узгоджені з рештою rule-перевірок у `npm/rules`.
46
+ checkвиконує перевірку hasura.mdc для поточного робочого каталогу.
319
47
 
320
- ### Сценарій 5. Граничні випадки
48
+ ## Гарантії поведінки
321
49
 
322
- - **Файл `.env`** (без імені, локальний розробницький) **пропускається** на рівні `isEnvFile`.
323
- - **Відсутнє `repository` в `package.json`** правило пропускається з `pass`.
324
- - **YAML-файли відсутні / невалідні** відповідне поле `expected` стане `null` і перевірка сегмента не виконується (але формат URL все одно валідується).
325
- - **`HASURA_GRAPHQL_ENDPOINT` у `.env` закоментований через `#` після значення** → регулярка зупиниться на `#`, повернувши значення до коментаря.
326
- - **Значення в подвійних/одинарних лапках** → лапки відкидаються регуляркою-капчуром.
50
+ - Read-only: файл не виконує операцій запису у файлову систему.
51
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
52
+ - За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
53
+ - Не звертається до мережі.