@nitra/cursor 5.2.0 → 5.3.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.
@@ -1,25 +1,27 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/ga/fix.mjs
4
+ crc: 12fc1644
5
+ score: 100
6
+ ---
7
+
1
8
  # fix.mjs
2
9
 
3
10
  ## Огляд
4
11
 
5
- Цей файл запускає процес перевірки наявності та стану необхідних системних ресурсів. Він забезпечує швидку оцінку готовності системи до подальшої роботи, використовуючи кешовані дані для прискорення процесу. Результати перевірки використовуються для прийняття рішень щодо подальших дій.
12
+ Модуль відповідає за запуск механізму виконання стандартного правила. Він шукає та застосовує правила, використовуючи поточний каталог як джерело. При запуску як окрема програма, він ініціює виконання команди, необхідної для застосування цього правила.
6
13
 
7
14
  ## Поведінка
8
15
 
9
- 1. Ініціалізує контекст прогону.
10
- 2. Викликає стандартне правило, використовуючи контекст.
11
- 3. Якщо код виконується як окремий CLI-скрипт, то:
12
- 1. Викликає оркестрацію правил.
13
- 2. Повертає код завершення процесу.
16
+ 1. Викликає механізм виконання стандартного правила, використовуючи поточний каталог як джерело правил.
17
+ 2. Якщо скрипт виконується як окрема програма, запускає оркестрацію командного рядка для виконання правила.
14
18
 
15
19
  ## Публічний API
16
20
 
17
- - run — Запускає стандартне правило, враховуючи контекст та перетворюючи його на JS-коду, політику та посилання на MDC.
18
- - Library mode — Викликається через CLI-оркестрацію за допомогою імпорту та функції `run`.
21
+ run — виконує послідовність дій: застосовує правила, обробляє JS-занепокоєння, перевіряє політику та посилання MDC.
19
22
 
20
23
  ## Гарантії поведінки
21
24
 
22
- - Запускає процес.
23
- - Кеш зберігає результати попередніх прогонів.
24
- - Результат залежить від попередніх прогонів.
25
- - Немає взаємодії з мережею.
25
+ - Read-only: файл не виконує операцій запису у файлову систему.
26
+ - Кешує результати в межах одного прогону.
27
+ - Не звертається до мережі.
@@ -1,19 +1,22 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/ga/js/lint.mjs
4
+ crc: 428bf482
5
+ score: 100
6
+ ---
7
+
1
8
  # lint.mjs
2
9
 
3
10
  ## Огляд
4
11
 
5
- Файл `lint` делегує перевірку коду інструменту, який запускається з командного рядка. Він використовується для автоматизованої перевірки коду на відповідність певним правилам. Це забезпечує консистентність та якість коду в проєкті.
12
+ Делегує застосування правил зовнішньому інструменту командного рядка. Параметр `files` ігнорується, оскільки режим перевірки на рівні окремих файлів відсутній. Публічна функція `lint` повертає код виходу інструменту, який визначає успішність або невдачу перевірки.
6
13
 
7
14
  ## Поведінка
8
15
 
9
- 1. Запускає наявний CLI для перевірки правил.
10
- 2. Проводить аналіз всього репозиторію, ігноруючи вказаний список файлів.
11
- 3. Повертає код завершення процесу.
12
- 4. Не використовує кеш результатів.
13
- 5. Не здійснює взаємодії з мережею.
16
+ 1. Викликає зовнішній інструмент для перевірки коду.
17
+ 2. Повертає код виходу цього інструменту.
14
18
 
15
19
  ## Гарантії поведінки
16
20
 
17
- - Делегує правила до існуючого CLI.
18
- - Не враховує `files` в режимі per-file.
19
- - Не має кешування.
21
+ - Read-only: файл не виконує операцій запису у файлову систему.
22
+ - Не звертається до мережі.
@@ -1,32 +1,33 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/ga/js/workflows.mjs
4
+ crc: a9296cf1
5
+ score: 100
6
+ ---
7
+
1
8
  # workflows.mjs
2
9
 
3
10
  ## Огляд
4
11
 
5
- Файл перевіряє GitHub Actions workflows на відповідність певним правилам та стандартам. Він забезпечує консистентність та якість workflow, виявляючи потенційні проблеми, такі як відсутність clean/lint workflow або використання непідтримуваних інструментів. Це частина автоматизованого процесу забезпечення дотримання найкращих практик при розробці GitHub Actions.
12
+ Модуль виявляє наявність інструменту `shellcheck` та підтверджує відповідність конфігурації проєкту правилам ga.mdc. Він перевіряє відповідність workflow-файлів Rego-полісі, наявність обов'язкових компонентів та коректність шляхів тригерів GitHub Actions. Модуль свідомо пропускає шляхи `.github` та `.git` під час перевірки.
6
13
 
7
14
  ## Поведінка
8
15
 
9
- - `checkShellcheckInstalled`: Перевіряє наявність бінарника `shellcheck` в системному PATH.
10
- - `checkGaWorkflowFiles`: Перевіряє наявність workflow-файлів з розширенням `.yml` та відсутність інших розширень.
11
- - `runAllGaRego`: Запускає Rego-перевірки для всіх workflow-файлів, використовуючи `conftest` для аналізу.
12
- - `check`: Координує всі перевірки, включаючи Rego-аналіз, перевірку workflow-структури та перевірку наявність файлів.
16
+ checkShellcheckInstalled перевіряє наявність бінарника `shellcheck` у системному шляху, щоб забезпечити узгодженість локальних та CI-перевірок (ga.mdc).
17
+ check виконує комплексну валідацію конфігурації проєкту щодо правил ga.mdc, включаючи структурну перевірку workflow-файлів за допомогою Rego-полісі, перевірку наявності обов'язкових компонентів, валідацію шляхів тригерів GitHub Actions, пошук залишків MegaLinter та перевірку наявності `shellcheck` (ga.mdc). При цьому ігнорує директорії `.github` та `.git`.
13
18
 
14
19
  ## Публічний API
15
20
 
16
- - checkShellcheckInstalled — Перевіряє наявність `shellcheck` у системі та зупиняє workflow, якщо його немає.
17
- - check — Перевіряє відповідність проєкту правилам валідації.
18
- - runAllGaRego Запускає Rego-перевірку правил, як перший етап валідації.
19
- - lint-ga — Запускає перевірку `bun lint-ga` з використанням `actionlint` та `zizmor`.
21
+ checkShellcheckInstalled — визначає, чи встановлено `shellcheck` у системному шляху. Це дозволяє `actionlint` запускати перевірки скриптів лише тоді, коли інструмент доступний локально.
22
+
23
+ checkпорівнює структуру проєкту з вимогами, визначеними у правилах (ga.mdc).
24
+
25
+ Plan B-патерн — виконує первинну перевірку структури робочого процесу за допомогою Rego-полісі. Потім виконує перевірки на рівні JavaScript, включаючи пошук файлів та конфігурацій. Команда `bun run lint-ga` повторно викликає цю ж перевірку, використовуючи зовнішні інструменти.
20
26
 
21
27
  ## Гарантії поведінки
22
28
 
23
- - Гарантується наявність файлів `package.json`, `.vscode/*` та `.github/zizmor.yml`.
24
- - Гарантується, що workflow використовує `actions/checkout@v6` перед локальними операціями.
25
- - Гарантується, що workflow використовує composite action `action.yml` з `npx @nitra/cursor`.
26
- - Гарантується, що workflow містить `clean-ga-workflows.yml`, `clean-merged-branch.yml`, `lint-ga.yml` та `git-ai.yml`.
27
- - Гарантується, що workflow використовує `concurrency` для паралельного виконання.
28
- - Гарантується, що workflow не містить `oven-sh/setup-bun`, `actions/cache`, `bun install` у `uses` або `run`.
29
- - Гарантується, що workflow не використовує shell-продовження `\` у `run`.
30
- - Гарантується, що workflow використовує `shellcheck` локально.
31
- - Гарантується, що workflow перевіряє наявність файлів за допомогою `git ls-files :(glob)` та `on.*.paths`.
32
- - Гарантується, що workflow перевіряє наявність файлів, що залишилися від MegaLinter.
29
+ - Read-only: файл не виконує операцій запису у файлову систему.
30
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
31
+ - За невдалої перевірки повертає `false`/`null` замість винятку.
32
+ - Свідомо пропускає шляхи: `.github`, `.git`.
33
+ - Не звертається до мережі.
@@ -1,264 +1,29 @@
1
- # tooling.mjs
2
-
3
- ## Огляд
4
-
5
- Модуль `npm/rules/graphql/js/tooling.mjs` — це **check-скрипт правила `graphql.mdc`**, який перевіряє, що репозиторій налаштований для роботи з GraphQL за наявності у коді tagged template literals `gql\`...\``.
6
-
7
- Логіка перевірки **умовна**:
8
-
9
- 1. Скрипт рекурсивно обходить дерево проєкту з кореня (`process.cwd()` за замовчуванням) і збирає файли-кандидати (`.vue`, `.js`, `.ts`, `.jsx`, `.tsx` тощо) — пропускаючи службові артефакти типу `.d.ts`, `auto-imports.d.ts` тощо.
10
- 2. Для кожного кандидата виконує AST-сканування (oxc-parser; для `.vue` — після витягування блоку `<script>`) у пошуках `gql` tagged template literal.
11
- 3. Якщо **жодного збігу не знайдено** — перевірка завершується успішно й нічого більше не вимагає.
12
- 4. Якщо `gql\`…\`` **знайдено хоча б в одному файлі** — модуль вимагає:
13
- - наявність файлу `.graphqlrc.yml` у корені репозиторію (GraphQL Config);
14
- - відповідність `.vscode/extensions.json` rego-пакету `graphql.vscode_extensions` (тобто рекомендацію розширення VS Code `graphql.vscode-graphql`).
15
-
16
- Модуль є частиною інфраструктури `n-cursor` для перевірок правил `.mdc` і дотримується контракту check-скрипта: повертає exit code `0` при успіху й `1` при порушенні.
17
-
18
- ## Експорти / API
19
-
20
- | Експорт | Тип | Призначення |
21
- | ----------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------- |
22
- | `GRAPHQL_RC_FILENAME` | `string` (const, `.graphqlrc.yml`) | Очікувана назва файлу GraphQL Config у корені проєкту (з `graphql.mdc`). |
23
- | `REQUIRED_GRAPHQL_VSCODE_EXTENSION` | `string` (const, `graphql.vscode-graphql`) | Ідентифікатор обов'язкового розширення VS Code, яке має бути в `recommendations`. |
24
- | `check(cwd?)` | `async function` | Основна точка входу — виконує всю перевірку правила `graphql.mdc` і повертає exit code. |
25
-
26
- Внутрішні (не експортовані) хелпери:
27
-
28
- - `collectScanCandidates(root, ignorePaths)` — збір абсолютних шляхів файлів для сканування.
29
- - `collectGqlHits(root, candidates)` — фільтрація кандидатів за наявністю `gql` tagged template.
30
- - `checkExtensionsRecommendation(pass, fail, cwd)` — делегування перевірки `.vscode/extensions.json` rego-пакету `graphql.vscode_extensions` через `conftest`.
31
-
32
- ## Функції
33
-
34
- ### `collectScanCandidates(root, ignorePaths)`
35
-
36
- **Сигнатура:**
37
-
38
- ```js
39
- async function collectScanCandidates(root: string, ignorePaths: string[]): Promise<string[]>
40
- ```
41
-
42
- **Параметри:**
43
-
44
- - `root` — абсолютний шлях до кореня репозиторію, з якого починається обхід.
45
- - `ignorePaths` — масив абсолютних шляхів каталогів, які повністю виключаються з обходу (формується через `loadCursorIgnorePaths`).
46
-
47
- **Що робить:**
48
-
49
- - Викликає `walkDir(root, visitor, ignorePaths)` (рекурсивний обхід файлової системи).
50
- - Для кожного відвіданого файлу обчислює відносний шлях від `root`, нормалізує роздільники (Windows `\` → POSIX `/`).
51
- - Застосовує два фільтри:
52
- - `shouldSkipFileForGqlScan(rel)` — пропуск службових файлів (`.d.ts`, `auto-imports.d.ts` тощо).
53
- - `isGqlScanSourceFile(rel)` — допуск лише відповідних розширень (Vue/JS/TS-сімейство).
54
- - Накопичує **абсолютні** шляхи прийнятих файлів у масив `candidates`.
55
-
56
- **Повертає:** `Promise<string[]>` — список абсолютних шляхів файлів-кандидатів.
57
-
58
- **Side effects:** читає метадані файлової системи (через `walkDir`); записів не робить.
59
-
60
1
  ---
61
-
62
- ### `collectGqlHits(root, candidates)`
63
-
64
- **Сигнатура:**
65
-
66
- ```js
67
- async function collectGqlHits(root: string, candidates: string[]): Promise<string[]>
68
- ```
69
-
70
- **Параметри:**
71
-
72
- - `root` — абсолютний шлях до кореня (для обчислення відносних шляхів у результаті).
73
- - `candidates` — список абсолютних шляхів файлів, отриманих від `collectScanCandidates`.
74
-
75
- **Що робить:**
76
-
77
- - Послідовно (`for-of` + `await`) для кожного абсолютного шляху:
78
- - обчислює відносний шлях і нормалізує роздільники до `/`;
79
- - читає вміст файлу через `readFile(absPath, 'utf8')`;
80
- - викликає `sourceFileHasGqlTaggedTemplate(content, rel)` — парсер AST oxc, що враховує особливості `.vue` (витягування `<script>`);
81
- - якщо результат `true` — додає **відносний** шлях до результуючого масиву `hits`.
82
-
83
- **Повертає:** `Promise<string[]>` — відносні шляхи файлів, у яких знайдено хоча б одне `gql` tagged template.
84
-
85
- **Side effects:** читання вмісту файлів з диска. Запис відсутній.
86
-
2
+ docgen:
3
+ source: npm/rules/graphql/js/tooling.mjs
4
+ crc: eb6b4713
5
+ score: 100
87
6
  ---
88
7
 
89
- ### `checkExtensionsRecommendation(pass, fail, cwd)`
90
-
91
- **Сигнатура:**
92
-
93
- ```js
94
- function checkExtensionsRecommendation(
95
- pass: (msg: string) => void,
96
- fail: (msg: string) => void,
97
- cwd: string
98
- ): void
99
- ```
100
-
101
- **Параметри:**
102
-
103
- - `pass` — функція-репортер «успішно» (отримана з `createCheckReporter()`).
104
- - `fail` — функція-репортер «порушення».
105
- - `cwd` — абсолютний корінь репозиторію.
106
-
107
- **Що робить:**
108
-
109
- 1. Формує відносний (`.vscode/extensions.json`) і абсолютний шляхи до файлу VS Code-конфігу.
110
- 2. Якщо файл **не існує** (`existsSync`) — викликає `fail(...)` з повідомленням про те, що треба створити файл і додати `graphql.vscode-graphql` у `recommendations`, посилаючись на `graphql.mdc`. Виходить.
111
- 3. Інакше викликає `runConftestBatch({ policyDirRel: 'graphql/vscode_extensions', namespace: 'graphql.vscode_extensions', files: [pathAbs] })` — делегує перевірку rego-пакету conftest-у.
112
- 4. Якщо `violations.length === 0` — викликає `pass(...)` з повідомленням про відповідність. Інакше — для кожного порушення `v` викликає `fail(v.message)`.
113
-
114
- **Повертає:** нічого (`void`). Результати фіксуються через `pass` / `fail`.
115
-
116
- **Side effects:**
117
-
118
- - читання `.vscode/extensions.json` через зовнішній conftest-процес;
119
- - виклик `conftest` (binary) усередині `runConftestBatch`;
120
- - зміна стану внутрішнього reporter-у (накопичення успіхів/порушень).
121
-
122
- **Виклик умовний:** виконується лише після того, як основна функція `check` виявила `gql` у дереві.
123
-
124
- ---
125
-
126
- ### `check(cwd = process.cwd())`
127
-
128
- **Сигнатура:**
129
-
130
- ```js
131
- export async function check(cwd?: string): Promise<number>
132
- ```
133
-
134
- **Параметри:**
135
-
136
- - `cwd` — _необов'язковий_ абсолютний шлях до кореня репозиторію. За замовчуванням `process.cwd()`.
137
-
138
- **Що робить (потік):**
139
-
140
- 1. Створює репортер `createCheckReporter()` і деструктурує з нього `pass`, `fail`.
141
- 2. Завантажує список ігнорованих шляхів через `loadCursorIgnorePaths(root)`.
142
- 3. Викликає `collectScanCandidates(root, ignorePaths)` — отримує список файлів-кандидатів.
143
- 4. Викликає `collectGqlHits(root, candidates)` — отримує файли з `gql`.
144
- 5. **Розгалуження:**
145
- - Якщо `hits.length === 0` — викликає `pass(...)` з повідомленням «немає `gql\`…\``у джерелах, переглянуто N файлів —`.graphqlrc.yml`не вимагається» і **повертає**`reporter.getExitCode()`(зазвичай`0`).
146
- - Інакше викликає `pass(...)` зі звітом про N файлів (з перших 5 з суфіксом `…` якщо більше).
147
- 6. Перевіряє наявність `GRAPHQL_RC_FILENAME` (`.graphqlrc.yml`) у корені через `existsSync`:
148
- - Існує → `pass('.graphqlrc.yml існує')`.
149
- - Не існує → `fail(...)` з вимогою додати GraphQL Config (з посиланням на `graphql.mdc`).
150
- 7. Викликає `checkExtensionsRecommendation(pass, fail, root)` для перевірки `.vscode/extensions.json`.
151
- 8. Повертає `reporter.getExitCode()`: `0` — усі перевірки пройдені, `1` — є хоча б одне порушення.
152
-
153
- **Повертає:** `Promise<number>` — exit code (`0` — OK, `1` — порушення).
154
-
155
- **Side effects:**
156
-
157
- - читання файлової системи (метадані + вміст файлів кандидатів);
158
- - читання `.cursor/...` ignore-конфігу;
159
- - читання `.vscode/extensions.json` (опосередковано через conftest);
160
- - запуск процесу `conftest` через `runConftestBatch`;
161
- - мутація стану внутрішнього reporter-у (накопичення pass/fail-повідомлень).
162
-
163
- ## Залежності
164
-
165
- ### Node.js builtins
166
-
167
- | Модуль | Що використовується | Призначення |
168
- | ------------------ | ------------------- | ---------------------------------------------------------------------------- |
169
- | `node:fs` | `existsSync` | Синхронна перевірка наявності `.graphqlrc.yml` та `.vscode/extensions.json`. |
170
- | `node:fs/promises` | `readFile` | Асинхронне читання вмісту файлів-кандидатів. |
171
- | `node:path` | `join`, `relative` | Збирання абсолютних шляхів і обчислення відносних шляхів від кореня. |
172
-
173
- ### Внутрішні модулі репозиторію
174
-
175
- - `../../../scripts/lib/check-reporter.mjs` — `createCheckReporter`: фабрика репортера зі стандартним інтерфейсом `pass` / `fail` / `getExitCode()`.
176
- - `../lib/graphql-gql-scan.mjs`:
177
- - `isGqlScanSourceFile(rel)` — предикат «це source-файл, який потенційно містить `gql`» (за розширенням);
178
- - `shouldSkipFileForGqlScan(rel)` — предикат «цей файл слід ігнорувати при скануванні» (`.d.ts`, `auto-imports.d.ts` тощо);
179
- - `sourceFileHasGqlTaggedTemplate(content, rel)` — AST-перевірка на наявність `gql\`...\``(через oxc-parser; для`.vue`— після витягування`<script>`).
180
- - `../../../scripts/lib/load-cursor-config.mjs` — `loadCursorIgnorePaths(root)`: повертає абсолютні шляхи каталогів, повністю виключених з обходу (узгоджено з іншими check-скриптами).
181
- - `../../../scripts/lib/run-conftest-batch.mjs` — `runConftestBatch({ policyDirRel, namespace, files })`: запускає `conftest` з rego-пакетом і повертає масив `violations` (об'єкти з `.message`).
182
- - `../../../scripts/utils/walkDir.mjs` — `walkDir(root, visitor, ignorePaths)`: рекурсивний обхід файлової системи з підтримкою списку ігнорування.
183
-
184
- ### Зовнішні артефакти (не імпортуються, але потрібні в runtime)
185
-
186
- - **`conftest`** як CLI-binary (запускається з `runConftestBatch`).
187
- - **Rego-політика** в `graphql/vscode_extensions` з namespace `graphql.vscode_extensions` (перевіряє `.vscode/extensions.json`).
188
- - **`.cursor/ignore`-конфіг** у корені (читається `loadCursorIgnorePaths`).
189
- - **`graphql.mdc`** — правило, яке цей check реалізує.
190
-
191
- ## Потік виконання / Використання
192
-
193
- ### Запуск як check
194
-
195
- Модуль використовується з єдиною експортованою функцією `check`:
196
-
197
- ```js
198
- import { check } from 'npm/rules/graphql/js/tooling.mjs'
199
-
200
- const exitCode = await check() // або await check('/absolute/path/to/repo')
201
- process.exit(exitCode)
202
- ```
203
-
204
- Типово викликається диспетчером check-скриптів інфраструктури `n-cursor` (наприклад, із `npm/scripts/...`), який отримує exit code й агрегує результати по всіх правилах `.mdc`.
8
+ # tooling.mjs
205
9
 
206
- ### Послідовність дій усередині `check`
10
+ ## Огляд
207
11
 
208
- ```
209
- process.cwd() (або переданий cwd)
210
-
211
-
212
- createCheckReporter() ──► { pass, fail, getExitCode }
213
-
214
-
215
- loadCursorIgnorePaths(root) ──► ignorePaths
216
-
217
-
218
- collectScanCandidates(root, ignorePaths)
219
- │ walkDir(root, visitor, ignorePaths)
220
- │ filter: !shouldSkipFileForGqlScan && isGqlScanSourceFile
221
-
222
- candidates: string[]
223
-
224
-
225
- collectGqlHits(root, candidates)
226
- │ for each: readFile + sourceFileHasGqlTaggedTemplate (oxc-parser AST)
227
-
228
- hits: string[]
229
-
230
- ├── hits.length === 0 ──► pass("немає gql у джерелах") ──► return 0
231
-
232
- └── hits.length > 0
233
-
234
- ├── pass("Знайдено gql у N файлі(ах): ...")
235
-
236
- ├── existsSync(.graphqlrc.yml)
237
- │ ├── true ──► pass(".graphqlrc.yml існує")
238
- │ └── false ──► fail("Відсутній .graphqlrc.yml ...")
239
-
240
- ├── checkExtensionsRecommendation(pass, fail, root)
241
- │ ├── !existsSync(.vscode/extensions.json) ──► fail(...)
242
- │ └── runConftestBatch(graphql/vscode_extensions)
243
- │ ├── violations.length === 0 ──► pass(...)
244
- │ └── for v of violations: fail(v.message)
245
-
246
- └── return reporter.getExitCode() (0 або 1)
247
- ```
12
+ Визначає ім'я файлу конфігурації (`GRAPHQL_RC_FILENAME` = ".graphqlrc.yml") та обов'язкове розширення VS Code (`REQUIRED_GRAPHQL_VSCODE_EXTENSION` = "graphql.vscode-graphql"). Перевіряє наявність конфігурації в `extensions.json` (конфігурація, на яку спирається код) та підтверджує необхідність розширення для роботи з GraphQL (graphql.mdc).
248
13
 
249
- ### Семантика повідомлень
14
+ ## Поведінка
250
15
 
251
- - `pass` інформативне повідомлення про успішну перевірку (логнеться як OK, не впливає на exit code).
252
- - `fail` повідомлення про порушення; навіть одне `fail` робить `getExitCode()` рівним `1`.
16
+ GRAPHQL_RC_FILENAME: Повертає ім'я файлу конфігурації GraphQL.
17
+ REQUIRED_GRAPHQL_VSCODE_EXTENSION: Повертає ім'я розширення VS Code, необхідне для GraphQL.
18
+ check: Перевіряє наявність `gql` tagged template у джерелах. Якщо знайдено, вимагає наявності `.graphqlrc.yml` та валідує `.vscode/extensions.json` щодо `graphql.vscode-graphql` (graphql.mdc).
253
19
 
254
- ### Чому перевірка умовна
20
+ ## Публічний API
255
21
 
256
- `graphql.mdc` вимагає `.graphqlrc.yml` і VS Code-розширення `graphql.vscode-graphql` **лише** для проєктів, де реально використовуються `gql` tagged template literals. У монорепо це дозволяє не «спамити» правилом workspace-и, що не торкаються GraphQL check спочатку доводить релевантність (`hits.length > 0`), і лише потім вимагає інфраструктуру.
22
+ GRAPHQL_RC_FILENAME вказує на файл конфігурації GraphQL у корені проєкту (graphql.mdc).
23
+ REQUIRED_GRAPHQL_VSCODE_EXTENSION — вимагає встановлення розширення `graphql.vscode-graphql` для роботи з graphql.mdc.
24
+ check — перевіряє наявність файлу `.graphqlrc.yml` та розширення `graphql.vscode-graphql` при використанні тегів GraphQL.
257
25
 
258
- ### Обмеження та особливості
26
+ ## Гарантії поведінки
259
27
 
260
- - Шляхи в `hits` та в попередженнях завжди **відносні** до `root`, з POSIX-роздільниками `/` (навіть на Windows).
261
- - Перші 5 файлів-збігів показуються у повідомленні `pass`; решта приховується за суфіксом `…`.
262
- - Якщо `gql` знайдено, але `.vscode/extensions.json` відсутній — це порушення, незалежне від rego-перевірки (тобто `fail` без виклику conftest).
263
- - `collectGqlHits` читає файли **послідовно** (без `Promise.all`) — це навмисно, щоб не перевантажувати I/O при великих репозиторіях.
264
- - Виявлення `gql` — на рівні AST (oxc-parser), а не регулярних виразів; рядкові збіги типу `// gql\`...\`` у коментарі не дають false-positive.
28
+ - Read-only: файл не виконує операцій запису у файлову систему.
29
+ - Не звертається до мережі.
@@ -1,120 +1,27 @@
1
- # fix.mjs — entry-point правила `hasura`
1
+ ---
2
+ docgen:
3
+ source: npm/rules/hasura/fix.mjs
4
+ crc: 12fc1644
5
+ score: 100
6
+ ---
2
7
 
3
- ## Огляд
4
-
5
- Файл `npm/rules/hasura/fix.mjs` — тонкий entry-point для правила з ідентифікатором `hasura` у складі CLI-пакета `@nitra/cursor`. Виконує дві ролі одночасно:
6
-
7
- 1. **Library mode** — експортує функцію `run(ctx)`, яка викликається з оркестратора CLI (наприклад, з `runRuleCli` або з агрегаторів типу `n-fix`), що дозволяє запускати правило в межах загального прогону всіх правил без породження окремого процесу.
8
- 2. **Standalone mode** — якщо файл виконується безпосередньо (через `bun rules/<id>/fix.mjs` або `node rules/<id>/fix.mjs`), він виступає самостійним CLI-входом, повністю еквівалентним `npx @nitra/cursor fix hasura`: підвантажує config, застосовує whitelist, друкує summary та повертає процесний exit-code.
9
-
10
- Уся фактична логіка правила (послідовність кроків `applies → JS-concerns → policy → mdc-refs`) винесена в спільну реалізацію `runStandardRule` із бібліотечного шару `scripts/lib/`. Файл-обгортка несе лише прив'язку правила до власної директорії (через `import.meta.dirname`) та dispatch між двома режимами запуску.
11
-
12
- Відповідає конвенції двороль­ового `fix.mjs`, ухваленій для всіх «стандартних» правил у `npm/rules/*/`, тож має мінімальну поверхню коду й не містить специфіки `hasura`: тип правила, скоупи, перевірки та поліcі описуються деінде (`meta.json`, `hasura.mdc`, `js/`, `policy/`).
13
-
14
- ## Експорти / API
15
-
16
- | Експорт | Тип | Призначення |
17
- | ------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
18
- | `run` | `(ctx?: RuleContext) => Promise<number>` | Library-mode прогін правила в спільному CLI orchestration. Повертає `0` при відсутності порушень або `1` при наявності порушень. |
19
-
20
- Файл не має `default`-експорту й не експортує жодних інших символів.
21
-
22
- Поведінка при безпосередньому запуску файлу як скрипта — побічний ефект (top-level `await runRuleCli(...)` + `process.exit(...)`) і не є частиною програмного API.
23
-
24
- ## Функції
25
-
26
- ### `run(ctx)`
27
-
28
- Сигнатура: `export function run(ctx)`.
29
-
30
- - **Параметри:**
31
- - `ctx` (`RuleContext`, опційний) — контекст прогону, що передається з оркестратора. Тип імпортовано (через JSDoc-tag `@param`) з `../../scripts/lib/run-standard-rule.mjs`. Очікувані поля контексту (за конвенцією `runStandardRule`) — спільні для всіх правил, серед них зокрема `walkCache` (кеш обходу файлової системи, щоб не повторювати walk між кількома правилами в одному прогоні). Якщо `ctx` не передано (`undefined`), `runStandardRule` сам ініціалізує мінімально необхідний контекст.
32
- - **Повертає:** `Promise<number>` — exit-code правила:
33
- - `0` — застосовні файли пройшли всі етапи (`applies → JS-concerns → policy → mdc-refs`) без виявлених порушень.
34
- - `1` — знайдено принаймні одне порушення (або зафіксована помилка валідації, що інтерпретується як failure).
35
- - **Side effects:**
36
- - Делегує всю роботу `runStandardRule(import.meta.dirname, ctx)`, який, своєю чергою, читає файли правила (`meta.json`, `*.mdc`, `js/*.mjs`, `policy/*.rego`) із директорії, обходить цільові файли проєкту, друкує діагностичні повідомлення у stdout/stderr та повертає підсумкове число порушень. Сам `run` стану не модифікує.
37
- - Прив'язує правило до своєї директорії саме через `import.meta.dirname`, тож при переміщенні файлу `fix.mjs` правило автоматично «переїде» разом із його артефактами (без хардкоду шляхів).
38
-
39
- ### Безіменна процедура top-level (standalone-блок)
8
+ # fix.mjs
40
9
 
41
- ```js
42
- if (isRunAsCli(import.meta.url)) {
43
- process.exit(await runRuleCli(import.meta.dirname))
44
- }
45
- ```
46
-
47
- - **Тип:** виконується один раз під час завантаження модуля.
48
- - **Параметри:** немає (CLI-аргументи зчитуються всередині `runRuleCli` через `process.argv`).
49
- - **Повертає:** нічого (виконує `process.exit`).
50
- - **Side effects:**
51
- - `isRunAsCli(import.meta.url)` визначає, чи модуль завантажено як прямий entry-point (а не як `import`).
52
- - У випадку прямого запуску викликає `runRuleCli(import.meta.dirname)`, який повертає числовий exit-code, і негайно завершує процес із цим кодом через `process.exit`.
53
- - Через `process.exit` подальші асинхронні задачі (мікротаски, відкриті ресурси) можуть бути обірвані — це свідомо: standalone entry-point повинен повертати чіткий код для CI/IDE-інтеграцій.
54
- - **Локальні правила лінту:**
55
- - Поряд із викликом стоїть прагма `// eslint-disable-next-line n/no-process-exit, unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE`, оскільки за загальним правилом `process.exit` заборонений, але для CLI-входів дозволений.
56
-
57
- ## Залежності
58
-
59
- ### Внутрішні (відносні імпорти)
60
-
61
- - `../../scripts/lib/run-rule-cli.mjs`
62
- - `isRunAsCli(metaUrl: string): boolean` — детектор «чи запущено модуль як скрипт». Зазвичай порівнює `import.meta.url` із URL виконуваного скрипта (`process.argv[1]`), щоб розрізнити `import` та прямий запуск.
63
- - `runRuleCli(ruleDir: string): Promise<number>` — повноцінний CLI-runner: парсить аргументи, читає глобальний config (whitelist, severity, опції), запускає правило з директорії `ruleDir` і друкує summary. Повертає exit-code.
64
- - `../../scripts/lib/run-standard-rule.mjs`
65
- - `runStandardRule(ruleDir: string, ctx?: RuleContext): Promise<number>` — стандартна послідовність кроків для «звичайного» правила: `applies → JS-concerns → policy → mdc-refs`. Це публічне ядро правил-обгорток на кшталт `fix.mjs`.
66
- - `RuleContext` (тип) — імпортовано лише в JSDoc для типізації параметра `run`.
67
-
68
- ### Зовнішні
69
-
70
- Прямих залежностей від npm-пакетів файл не має. Усі сторонні бібліотеки, які можуть знадобитися (наприклад, walker, парсер `.mdc`, OPA-обгортки тощо), використовуються транзитивно через `run-standard-rule.mjs` та `run-rule-cli.mjs`.
71
-
72
- ### Залежність від файлів-побратимів у директорії правила
73
-
74
- Хоча `fix.mjs` сам нічого з них не читає, `runStandardRule(import.meta.dirname)` спирається на сусідні артефакти у тій же директорії правила `hasura/`:
75
-
76
- - `meta.json` — метадані правила (id, scope, опції тощо);
77
- - `hasura.mdc` — людинозрозумілий опис правила у форматі Cursor `.mdc`;
78
- - `js/` — JS-перевірки правила (`check-*.mjs`, fix-helpers);
79
- - `policy/` — Rego-полісі для OPA-кроку.
80
-
81
- Тож структурно файл `fix.mjs` має сенс лише як частина повної папки правила.
82
-
83
- ## Потік виконання / Використання
84
-
85
- ### Сценарій A — Library mode (з оркестратора)
10
+ ## Огляд
86
11
 
87
- 1. Оркестратор (`n-cursor` CLI, агрегатор скілів, тести) робить `import { run } from '<path>/npm/rules/hasura/fix.mjs'`.
88
- 2. Викликає `await run(ctx)`, передаючи контекст із попередньо побудованим `walkCache` та іншими опціями.
89
- 3. `run` синхронно повертає результат виклику `runStandardRule(import.meta.dirname, ctx)`.
90
- 4. `runStandardRule`:
91
- - читає `meta.json` із директорії правила;
92
- - проганяє послідовність `applies` (фільтр цільових файлів) → JS-concerns (динамічно підвантажені `js/check-*.mjs`) → policy (OPA з `policy/*.rego`) → mdc-refs (валідація `.mdc`-посилань);
93
- - агрегує знахідки й повертає кількість порушень як exit-code (`0`/`1`).
94
- 5. Оркестратор підсумовує exit-коди всіх правил.
12
+ Цей файл ініціює застосування правил. Він запускає процес, що включає перевірку JS-занепокоєнь та політик. При самостійному запуску скрипт завантажує конфігурацію та вайтлістинг, а також надає звіт про виконання.
95
13
 
96
- ### Сценарій B — Standalone CLI
14
+ ## Поведінка
97
15
 
98
- 1. Користувач/CI виконує `bun npm/rules/hasura/fix.mjs [args...]`.
99
- 2. На завантаженні модуля Node/Bun обчислює `isRunAsCli(import.meta.url)` для прямого запуску результат `true`.
100
- 3. Виконується `await runRuleCli(import.meta.dirname)`:
101
- - парсинг CLI-аргументів (`--whitelist`, `--severity`, прапори `-q`/`-v` тощо — деталі в `run-rule-cli.mjs`);
102
- - підвантаження конфіг-файлу пакета;
103
- - застосування whitelist;
104
- - виклик внутрішнього еквівалента `runStandardRule` для цієї ж директорії;
105
- - друк summary-таблиці результатів.
106
- 4. `process.exit(<exit-code>)` миттєво завершує процес зі значенням, яке повернув `runRuleCli`.
16
+ 1. Викликати функцію `run` для виконання правила. Це ініціює процес застосування правил, включаючи перевірку JS-занепокоєнь, політик та посилань MDC.
17
+ 2. Якщо скрипт виконується як окрема утиліта (standalone), викликати механізм оркестрації для виконання правила. Це забезпечує повну функціональність, включаючи завантаження конфігурації, вайтлістинг та підсумок.
107
18
 
108
- ### Типові випадки використання
19
+ ## Публічний API
109
20
 
110
- - **CI:** `bun npm/rules/hasura/fix.mjs` як standalone-крок у пайплайні; ненульовий exit-code зриває build.
111
- - **Локально:** `npx @nitra/cursor fix hasura` запускає той самий entry-point через диспетчер CLI пакета (а не напряму).
112
- - **Інтеграція в IDE:** редактор може імпортувати `run` і викликати його в окремому процесі для отримання структурованого результату по правилу `hasura` (наприклад, через виклик `bun -e "import('...fix.mjs').then(m => m.run())"`).
113
- - **Агрегатори скілів** (наприклад, `n-fix`): паралельно або послідовно імпортують `run` із усіх правил `npm/rules/*/fix.mjs`, передають спільний `ctx` із `walkCache`, щоб уникнути повторного обходу файлової системи.
21
+ run виконує послідовність дій: застосовує правила, обробляє JavaScript-занепокоєння, перевіряє політику та посилання MDC.
114
22
 
115
- ### Технічні зауваження щодо реалізації
23
+ ## Гарантії поведінки
116
24
 
117
- - `import.meta.dirname` (Node 20.11 / Bun) повертає абсолютний шлях до директорії модуля без потреби в `fileURLToPath(import.meta.url)`. Це поточний рекомендований спосіб локалізації власної директорії в ESM-модулях.
118
- - Прапор `await` у `process.exit(await runRuleCli(...))` працює завдяки top-level await у ESM — додаткової `main()`-обгортки не потрібно.
119
- - Свідомо обираний `process.exit` (а не «м'який» вихід через `process.exitCode = ...`) гарантує детермінований код повернення для CI/IDE навіть якщо хтось у фоновому таску щось «недописав».
120
- - Файл нейтральний щодо помилок: `runStandardRule` та `runRuleCli` самі вирішують, чи виносити exception у консоль і конвертувати її в exit-code; `fix.mjs` не обгортає виклики в `try/catch`.
25
+ - Read-only: файл не виконує операцій запису у файлову систему.
26
+ - Кешує результати в межах одного прогону.
27
+ - Не звертається до мережі.
@@ -2,7 +2,7 @@
2
2
  description: Використання pg / mysql2 / Bun SQL у Node.js та Bun
3
3
  globs: "**/package.json,**/src/conn/**"
4
4
  alwaysApply: false
5
- version: '1.14'
5
+ version: '1.15'
6
6
  ---
7
7
 
8
8
  ## Підтримувані версії баз даних
@@ -300,10 +300,10 @@ const rows = await sql.unsafe(query, values)
300
300
 
301
301
  Дефолтний експорт `sql` з `'bun'` сам читає змінні середовища (`DATABASE_URL`, `POSTGRES_URL`, `MYSQL_URL`, `PGHOST`/`PGUSER`/... та `MYSQL_HOST`/`MYSQL_USER`/...) і керує пулом — окремий `Pool` як у `pg` створювати не треба.
302
302
 
303
- Для явного конфігу — `new SQL(...)` як **singleton** на рівні модуля, а не на кожен запит. Файл кладеться у `src/conn/db.js` і експортує іменовані константи `pgWrite` (основний запис) та `pgRead` (read-only replica), щоб glob `**/src/conn/**` у правилах покривав ці файли:
303
+ Для явного конфігу — `new SQL(...)` як **singleton** на рівні модуля, а не на кожен запит. Файл кладеться у `src/conn/db.mjs` і експортує іменовані константи `pgWrite` (основний запис) та `pgRead` (read-only replica), щоб glob `**/src/conn/**` у правилах покривав ці файли:
304
304
 
305
305
  ```javascript
306
- // src/conn/db.js
306
+ // src/conn/db.mjs
307
307
  import { SQL } from 'bun'
308
308
 
309
309
  export const pgWrite = new SQL({
@@ -454,16 +454,16 @@ ${pgRead.array(ids, 'int4')}
454
454
 
455
455
  OXC formatter (oxfmt ≥ 0.49) примусово розгортає будь-який `CallExpression`, де перший аргумент є `CallExpression` з callback, у багаторядковий блок — незалежно від `printWidth`. Тому `pgWrite.array(arr.map(r => r.field), 'type')` всередині tagged template literal завжди стає 4-рядковим блоком. `col(arr, 'field')` (перший аргумент — identifier, другий — string literal) цей тригер не зачіпає і лишається однорядковим.
456
456
 
457
- Канонічне місце хелпера — `src/utils/col.js` (або `src/conn/col.js` залежно від структури проєкту):
457
+ Канонічне місце хелпера — `src/utils/col.mjs` (або `src/conn/col.mjs` залежно від структури проєкту):
458
458
 
459
459
  ```javascript
460
- // src/utils/col.js
460
+ // src/utils/col.mjs
461
461
  export const col = (arr, key) => arr.map(r => r[key])
462
462
  ```
463
463
 
464
464
  ```javascript
465
- import { pgWrite } from '#src/conn/db.js'
466
- import { col } from '#src/utils/col.js'
465
+ import { pgWrite } from '#src/conn/db.mjs'
466
+ import { col } from '#src/utils/col.mjs'
467
467
 
468
468
  // ❌ oxfmt розгортає на 4+ рядки незалежно від printWidth
469
469
  ${pgWrite.array(rows.map(r => r.id), 'int4')}