@nitra/cursor 3.22.0 → 3.23.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.
- package/.pi-template/extensions/n-cursor-adr/docs/index.md +181 -0
- package/CHANGELOG.md +31 -3
- package/bin/docs/n-cursor.md +636 -0
- package/bin/docs/rename-yaml-extensions.md +207 -0
- package/bin/n-cursor.js +30 -3
- package/package.json +1 -1
- package/rules/abie/docs/fix.md +18 -0
- package/rules/abie/js/docs/applies.md +26 -0
- package/rules/abie/js/docs/env_dns.md +32 -0
- package/rules/abie/js/docs/firebase_hosting.md +23 -0
- package/rules/abie/js/docs/hc_pairing.md +35 -0
- package/rules/abie/js/docs/ua_http_route.md +28 -0
- package/rules/abie/js/docs/ua_node_selector.md +28 -0
- package/rules/abie/lib/docs/enabled.md +29 -0
- package/rules/abie/lib/docs/env-dns.md +35 -0
- package/rules/abie/lib/docs/hc-yaml.md +33 -0
- package/rules/abie/lib/docs/http-route.md +44 -0
- package/rules/abie/lib/docs/k8s-tree.md +40 -0
- package/rules/abie/lib/docs/kustomization-patches.md +47 -0
- package/rules/abie/lib/docs/overlay-paths.md +38 -0
- package/rules/abie/lib/docs/yaml.md +29 -0
- package/rules/adr/docs/fix.md +148 -0
- package/rules/adr/js/docs/hooks.md +259 -0
- package/rules/bun/docs/fix.md +156 -0
- package/rules/bun/js/docs/layout.md +393 -0
- package/rules/capacitor/docs/fix.md +121 -0
- package/rules/capacitor/js/docs/platforms.md +295 -0
- package/rules/changelog/changelog.mdc +2 -2
- package/rules/changelog/docs/fix.md +174 -0
- package/rules/changelog/js/consistency.mjs +114 -13
- package/rules/changelog/js/docs/consistency.md +387 -0
- package/rules/changelog/lib/docs/package-manifest.md +210 -0
- package/rules/ci4/docs/fix.md +179 -0
- package/rules/ci4/js/docs/marksman_config.md +128 -0
- package/rules/docker/docker.mdc +8 -3
- package/rules/docker/docs/fix.md +171 -0
- package/rules/docker/js/docs/lint.md +258 -0
- package/rules/docker/lib/docs/docker-hadolint.md +184 -0
- package/rules/docker/lib/docs/docker-mirror.md +247 -0
- package/rules/docker/lib/docs/docker-native-addon.md +170 -0
- package/rules/docker/lib/docs/docker-nginx-user.md +219 -0
- package/rules/docker/lint/docs/lint.md +193 -0
- package/rules/efes/docs/fix.md +203 -0
- package/rules/feedback/docs/fix.md +140 -0
- package/rules/flow/docs/fix.md +152 -0
- package/rules/ga/docs/fix.md +158 -0
- package/rules/ga/js/docs/lint.md +100 -0
- package/rules/ga/js/docs/workflows.md +217 -0
- package/rules/ga/lint/docs/lint.md +209 -0
- package/rules/ga/policy/clean_merged_branch/clean_merged_branch.rego +11 -2
- package/rules/ga/policy/clean_merged_branch/template/clean-merged-branch.yml.snippet.yml +3 -4
- package/rules/graphql/docs/fix.md +126 -0
- package/rules/graphql/js/docs/tooling.md +264 -0
- package/rules/graphql/lib/docs/graphql-gql-scan.md +219 -0
- package/rules/hasura/docs/fix.md +120 -0
- package/rules/hasura/hasura.mdc +14 -0
- package/rules/hasura/js/docs/internal_urls.md +326 -0
- package/rules/image-avif/docs/fix.md +132 -0
- package/rules/image-avif/js/docs/avif_generation.md +241 -0
- package/rules/image-compress/docs/fix.md +150 -0
- package/rules/image-compress/js/docs/package_setup.md +191 -0
- package/rules/js-bun-db/docs/fix.md +148 -0
- package/rules/js-bun-db/js/docs/safety.md +231 -0
- package/rules/js-bun-db/js-bun-db.mdc +42 -13
- package/rules/js-bun-db/lib/docs/bun-sql-scan.md +347 -0
- package/rules/js-bun-redis/docs/fix.md +123 -0
- package/rules/js-bun-redis/js/docs/imports.md +176 -0
- package/rules/js-bun-redis/lib/docs/redis-imports.md +223 -0
- package/rules/js-lint/docs/fix.md +117 -0
- package/rules/js-lint/js/docs/lint.md +250 -0
- package/rules/js-lint/js/docs/tooling.md +348 -0
- package/rules/js-lint/js/docs/utils_imports.md +207 -0
- package/rules/js-lint-ci/docs/fix.md +154 -0
- package/rules/js-lint-ci/js/docs/lint.md +144 -0
- package/rules/js-mssql/docs/fix.md +128 -0
- package/rules/js-mssql/js/docs/deps.md +263 -0
- package/rules/js-mssql/lib/docs/mssql-pool-scan.md +367 -0
- package/rules/js-run/docs/fix.md +144 -0
- package/rules/js-run/js/docs/runtime.md +388 -0
- package/rules/js-run/lib/docs/bunyan-imports.md +117 -0
- package/rules/js-run/lib/docs/check-env-scan.md +433 -0
- package/rules/js-run/lib/docs/conn-file-rules.md +300 -0
- package/rules/js-run/lib/docs/conn-imports-scan.md +204 -0
- package/rules/js-run/lib/docs/promise-settimeout-scan.md +326 -0
- package/rules/k8s/docs/fix.md +129 -0
- package/rules/k8s/js/docs/manifests.md +344 -0
- package/rules/k8s/js/manifests.mjs +6 -2
- package/rules/k8s/k8s.mdc +4 -2
- package/rules/k8s/lint/docs/lint.md +411 -0
- package/rules/k8s/policy/network_policy/template/deployment.snippet.yaml +2 -0
- package/rules/k8s/policy/network_policy/template/stateful-set.snippet.yaml +2 -0
- package/rules/nginx-default-tpl/docs/fix.md +124 -0
- package/rules/nginx-default-tpl/js/docs/template.md +378 -0
- package/rules/npm-module/docs/fix.md +98 -0
- package/rules/npm-module/js/docs/package_structure.md +274 -0
- package/rules/npm-module/js/docs/rule_meta.md +137 -0
- package/rules/npm-module/js/docs/skill_meta.md +190 -0
- package/rules/php/docs/fix.md +107 -0
- package/rules/php/js/docs/tooling.md +152 -0
- package/rules/php/lint/docs/lint.md +215 -0
- package/rules/python/docs/fix.md +163 -0
- package/rules/python/js/docs/applies.md +108 -0
- package/rules/python/js/docs/tooling.md +153 -0
- package/rules/python/lint/docs/lint.md +322 -0
- package/rules/rego/docs/fix.md +121 -0
- package/rules/rego/js/docs/applies.md +174 -0
- package/rules/rego/js/docs/lint.md +118 -0
- package/rules/rego/lint/docs/lint.md +204 -0
- package/rules/release/docs/change.md +185 -0
- package/rules/release/docs/fix.md +119 -0
- package/rules/release/docs/release.md +222 -0
- package/rules/release/lib/docs/aggregate.md +246 -0
- package/rules/release/lib/docs/change-file.md +200 -0
- package/rules/release/lib/docs/fallback.md +203 -0
- package/rules/rust/docs/fix.md +129 -0
- package/rules/rust/js/docs/applies.md +140 -0
- package/rules/rust/lib/docs/has-cargo-toml.md +130 -0
- package/rules/security/docs/fix.md +86 -0
- package/rules/security/js/docs/lint.md +171 -0
- package/rules/security/js/docs/sample_secret.md +190 -0
- package/rules/security/js/docs/trufflehog.md +137 -0
- package/rules/security/js/lint.mjs +9 -1
- package/rules/style-lint/docs/fix.md +155 -0
- package/rules/style-lint/js/docs/lint.md +184 -0
- package/rules/style-lint/js/docs/tooling.md +194 -0
- package/rules/tauri/docs/fix.md +158 -0
- package/rules/tauri/js/docs/cargo_mutants_config.md +168 -0
- package/rules/tauri/js/docs/tooling.md +228 -0
- package/rules/test/coverage/coverage.mjs +15 -3
- package/rules/test/docs/fix.md +132 -0
- package/rules/test/js/data/stryker_config/docs/stryker-vue-macros-ignorer.md +138 -0
- package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +134 -0
- package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +160 -0
- package/rules/test/js/data/vitest_config/docs/vitest.config.baseline.md +195 -0
- package/rules/test/js/docs/cargo_mutants_config.md +173 -0
- package/rules/test/js/docs/location.md +136 -0
- package/rules/test/js/docs/no-process-chdir.md +160 -0
- package/rules/test/js/docs/no-relative-fs-path.md +271 -0
- package/rules/test/js/docs/stryker_config.md +152 -0
- package/rules/test/js/docs/vitest-config-pool-forks.md +174 -0
- package/rules/text/docs/fix.md +118 -0
- package/rules/text/js/docs/forbidden-prettier.md +143 -0
- package/rules/text/js/docs/formatting.md +256 -0
- package/rules/text/js/docs/lint.md +122 -0
- package/rules/text/lint/docs/lint.md +220 -0
- package/rules/text/lint/docs/run-dotenv-linter.md +157 -0
- package/rules/text/lint/docs/run-shellcheck.md +212 -0
- package/rules/text/lint/docs/run-v8r.md +197 -0
- package/rules/vue/docs/fix.md +127 -0
- package/rules/vue/js/docs/packages.md +335 -0
- package/rules/vue/lib/docs/vue-forbidden-imports.md +261 -0
- package/rules/worktree/docs/fix.md +161 -0
- package/schemas/rule-meta.json +5 -1
- package/scripts/auto-rules.mjs +7 -4
- package/scripts/coverage-classify/docs/apply.md +202 -0
- package/scripts/coverage-classify/docs/cache.md +203 -0
- package/scripts/coverage-classify/docs/index.md +218 -0
- package/scripts/coverage-classify/docs/prompt.md +132 -0
- package/scripts/coverage-classify/docs/verdict-schema.md +169 -0
- package/scripts/coverage-fix-extract.mjs +122 -0
- package/scripts/coverage-fix.mjs +1 -1
- package/scripts/dispatcher/docs/graph.md +346 -0
- package/scripts/dispatcher/docs/index.md +236 -0
- package/scripts/dispatcher/docs/trace.md +296 -0
- package/scripts/dispatcher/index.mjs +1 -1
- package/scripts/dispatcher/lib/active.mjs +4 -8
- package/scripts/dispatcher/lib/commands.mjs +7 -11
- package/scripts/dispatcher/lib/docs/active.md +348 -0
- package/scripts/dispatcher/lib/docs/artifact.md +232 -0
- package/scripts/dispatcher/lib/docs/budget.md +167 -0
- package/scripts/dispatcher/lib/docs/capability.md +196 -0
- package/scripts/dispatcher/lib/docs/commands.md +210 -0
- package/scripts/dispatcher/lib/docs/events.md +182 -0
- package/scripts/dispatcher/lib/docs/executor.md +190 -0
- package/scripts/dispatcher/lib/docs/flow-lock.md +161 -0
- package/scripts/dispatcher/lib/docs/flow-resolve.md +267 -0
- package/scripts/dispatcher/lib/docs/gate.md +231 -0
- package/scripts/dispatcher/lib/docs/level.md +335 -0
- package/scripts/dispatcher/lib/docs/plan-panel.md +181 -0
- package/scripts/dispatcher/lib/docs/plan.md +200 -0
- package/scripts/dispatcher/lib/docs/planner.md +269 -0
- package/scripts/dispatcher/lib/docs/review.md +255 -0
- package/scripts/dispatcher/lib/docs/reviewer.md +240 -0
- package/scripts/dispatcher/lib/docs/snapshot.md +247 -0
- package/scripts/dispatcher/lib/docs/spec.md +203 -0
- package/scripts/dispatcher/lib/docs/state-store.md +303 -0
- package/scripts/dispatcher/lib/docs/subagent-runner.md +173 -0
- package/scripts/dispatcher/lib/executor.mjs +6 -1
- package/scripts/dispatcher/lib/flow-resolve.mjs +3 -1
- package/scripts/dispatcher/lib/level.mjs +29 -3
- package/scripts/dispatcher/lib/review.mjs +1 -1
- package/scripts/dispatcher/lib/subagent-runner.mjs +5 -3
- package/scripts/docs/auto-rules.md +376 -0
- package/scripts/docs/auto-skills.md +173 -0
- package/scripts/docs/build-agents-commands.md +183 -0
- package/scripts/docs/cli-entry.md +153 -0
- package/scripts/docs/coverage-fix.md +177 -0
- package/scripts/docs/ensure-nitra-cursor-dev-dependencies.md +189 -0
- package/scripts/lib/changed-files.mjs +4 -1
- package/scripts/lib/docs/changed-files.md +149 -0
- package/scripts/lib/docs/check-mdc-template-refs.md +222 -0
- package/scripts/lib/docs/check-reporter.md +175 -0
- package/scripts/lib/docs/discover-check-rules-from-cursor.md +157 -0
- package/scripts/lib/docs/discover-checkable-rules.md +165 -0
- package/scripts/lib/docs/ensure-tool.md +254 -0
- package/scripts/lib/docs/generated-markdown.md +275 -0
- package/scripts/lib/docs/gha-workflow.md +326 -0
- package/scripts/lib/docs/inline-template-links.md +303 -0
- package/scripts/lib/docs/list-rule-ids.md +156 -0
- package/scripts/lib/docs/load-cursor-config.md +147 -0
- package/scripts/lib/docs/mirror-parity.md +167 -0
- package/scripts/lib/worktree.mjs +26 -0
- package/scripts/worktree-cli.mjs +12 -2
- package/skills/coverage-fix/SKILL.md +34 -45
- package/skills/docgen/SKILL.md +44 -23
- package/skills/docgen/bench/etalon/firebase_hosting.md +19 -0
- package/skills/docgen/bench/etalon/k8s-tree.md +24 -0
- package/skills/docgen/bench/etalon/overlay-paths.md +24 -0
- package/skills/docgen/js/docgen-ignore.mjs +54 -0
- package/skills/docgen/js/docgen-scan.mjs +37 -21
- package/skills/llm-patch/SKILL.md +23 -2
- package/skills/start-check/SKILL.md +26 -53
- package/skills/start-check/js/check.mjs +211 -0
- package/skills/taze/SKILL.md +9 -3
- package/skills/taze/js/diff.mjs +154 -0
- package/types/bin/n-cursor.d.ts +1 -1
- package/skills/fix-tests/SKILL.md +0 -119
- package/skills/fix-tests/meta.json +0 -1
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# lint.mjs
|
|
2
|
+
|
|
3
|
+
## Огляд
|
|
4
|
+
|
|
5
|
+
Модуль `lint.mjs` — це «quick-крок» (швидкий етап) правила `style-lint`, який запускає `stylelint --fix` по стильових файлах проєкту: `*.css`, `*.scss`, `*.vue`. Модуль виконує дві окремі задачі:
|
|
6
|
+
|
|
7
|
+
1. Фільтрує довільний список шляхів, лишаючи з нього тільки файли зі стильовими розширеннями (`.css`, `.scss`, `.vue`).
|
|
8
|
+
2. Запускає виконуваний бінарник `stylelint` через `npx` з прапорцем `--fix` — або по точному списку файлів (режим «quick»), або по всьому glob-патерну `**/*.{css,scss,vue}` (режим «ci»).
|
|
9
|
+
|
|
10
|
+
Модуль написаний як ES-модуль (`.mjs`), не має побічних ефектів на рівні імпорту (не запускає `stylelint` під час завантаження модуля) і експортує дві функції: `filterStyleFiles` та `lint`.
|
|
11
|
+
|
|
12
|
+
Призначений для використання в інфраструктурі лінтінгу монорепо: викликається з оркестратора правил (наприклад, `tooling.mjs` сусіднього модуля), який передає або конкретний набір змінених файлів (швидкий цикл локального розробника), або `undefined` (повний прогін в CI).
|
|
13
|
+
|
|
14
|
+
## Експорти / API
|
|
15
|
+
|
|
16
|
+
Модуль має два іменованих експорти:
|
|
17
|
+
|
|
18
|
+
| Експорт | Тип | Призначення |
|
|
19
|
+
| ------------------ | ---------- | -------------------------------------------------------------------------- |
|
|
20
|
+
| `filterStyleFiles` | `function` | Чистий фільтр: з масиву шляхів повертає тільки `.css` / `.scss` / `.vue`. |
|
|
21
|
+
| `lint` | `function` | Запускає `stylelint --fix` через `npx`, повертає `Promise<number>` (exit). |
|
|
22
|
+
|
|
23
|
+
Дефолтного експорту немає.
|
|
24
|
+
|
|
25
|
+
Окрім експортів, у модулі визначена константа модульного рівня `STYLE_EXT_RE` — приватна (не експортується) регулярка `/\.(?:css|scss|vue)$/u`, яка матчить лише суфікс імені файлу.
|
|
26
|
+
|
|
27
|
+
## Функції
|
|
28
|
+
|
|
29
|
+
### `filterStyleFiles(files)`
|
|
30
|
+
|
|
31
|
+
**Сигнатура.**
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
export function filterStyleFiles(files: string[]): string[]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Параметри.**
|
|
38
|
+
|
|
39
|
+
- `files` — масив рядків-шляхів (відносних або абсолютних — функція не розрізняє). Жодних обмежень на роздільник шляху чи на регістр розширення регулярка не накладає, окрім того що розширення має бути в нижньому регістрі (`.css`, `.scss`, `.vue`).
|
|
40
|
+
|
|
41
|
+
**Повертає.**
|
|
42
|
+
|
|
43
|
+
- `string[]` — новий масив, що містить лише ті елементи `files`, у яких суфікс задовольняє регулярку `STYLE_EXT_RE` (`.css` / `.scss` / `.vue` в кінці рядка). Порядок збережено.
|
|
44
|
+
|
|
45
|
+
**Side effects.**
|
|
46
|
+
|
|
47
|
+
- Немає. Функція чиста: не змінює вхідний масив, не звертається до файлової системи, не пише в stdout/stderr, не залежить від процесового стану. Імпорт `node:child_process` тут не задіяний.
|
|
48
|
+
|
|
49
|
+
**Поведінкові деталі.**
|
|
50
|
+
|
|
51
|
+
- Якщо `files` — порожній масив, повертається порожній масив.
|
|
52
|
+
- Якщо в `files` немає жодного стильового файлу, повертається порожній масив.
|
|
53
|
+
- Файли з розширеннями `.CSS`, `.Vue` тощо (з великими літерами) **не** будуть включені, бо регулярка не має прапора `i`.
|
|
54
|
+
- Регулярка прив'язана до кінця рядка (`$`), тому шляхи на кшталт `foo.css.bak` не пройдуть.
|
|
55
|
+
- Прапор `u` (Unicode) у регулярці дозволяє коректно обробляти шляхи з Unicode-символами.
|
|
56
|
+
|
|
57
|
+
### `lint(files, cwd = process.cwd())`
|
|
58
|
+
|
|
59
|
+
**Сигнатура.**
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
export function lint(
|
|
63
|
+
files: string[] | undefined,
|
|
64
|
+
cwd?: string
|
|
65
|
+
): Promise<number>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Параметри.**
|
|
69
|
+
|
|
70
|
+
- `files` — або масив шляхів (тоді функція працює в режимі «quick»: фільтрує його через `filterStyleFiles` і запускає `stylelint` тільки по відфільтрованих файлах), або `undefined` (режим «ci»: запускає `stylelint` по glob-патерну `**/*.{css,scss,vue}` від кореня `cwd`).
|
|
71
|
+
- `cwd` — корінь, у якому запускатиметься `npx`. За замовчуванням — поточна робоча директорія процесу (`process.cwd()`).
|
|
72
|
+
|
|
73
|
+
**Повертає.**
|
|
74
|
+
|
|
75
|
+
- `Promise<number>` — обіцянка з exit-кодом:
|
|
76
|
+
- `0` — якщо `files` — масив, але після фільтрації не лишилось жодного стильового файлу (швидкий вихід без запуску `stylelint`).
|
|
77
|
+
- Числовий exit-код процесу `npx stylelint ...`, отриманий з поля `r.status` синхронного результату `spawnSync`.
|
|
78
|
+
- `1` — якщо `r.status` не є числом (наприклад, процес був завершений сигналом, не зміг запуститися або інша «нештатна» ситуація).
|
|
79
|
+
- Хоча всередині немає `async` й `await`, повертається явно `Promise.resolve(...)`, тож сигнатура асинхронна і викликати функцію можна через `await`.
|
|
80
|
+
|
|
81
|
+
**Side effects.**
|
|
82
|
+
|
|
83
|
+
- Запускає **зовнішній процес** `npx stylelint --fix ...` через `spawnSync` з `stdio: 'inherit'`. Це означає:
|
|
84
|
+
- `stdout`, `stderr`, `stdin` дочірнього процесу наслідуються від батьківського — весь вивід `stylelint` йде безпосередньо в консоль користувача (або в логи CI).
|
|
85
|
+
- Функція **блокує** event-loop поточного процесу до завершення `stylelint` (попри асинхронний інтерфейс).
|
|
86
|
+
- `stylelint --fix` **модифікує файли на диску** там, де він здатен автоматично виправити порушення стилю.
|
|
87
|
+
- Запис у файлову систему здійснюється самим `stylelint`, а не цим модулем напряму.
|
|
88
|
+
- Модуль не намагається інсталювати `stylelint` — він повинен бути доступний через `npx` (зазвичай через `package.json` залежність, локальний `node_modules/.bin` або глобально).
|
|
89
|
+
|
|
90
|
+
**Поведінкові деталі.**
|
|
91
|
+
|
|
92
|
+
- Аргументи `npx` будуються в масив `args`: завжди починається з `['stylelint', '--fix']`, далі або додається один елемент-glob `**/*.{css,scss,vue}`, або розпаковується список відфільтрованих файлів через spread.
|
|
93
|
+
- Glob-патерн `**/*.{css,scss,vue}` передається без екранування — його **розкриває сам `stylelint`** (а не shell), оскільки `spawnSync` викликається без `shell: true`. Тобто це не shell-glob, а аргумент, який `stylelint` парсить як glob-патерн.
|
|
94
|
+
- У режимі «quick» з порожнім результатом фільтрації функція не викликає `npx` взагалі — це оптимізація для випадків, коли в наборі змінених файлів немає жодного стильового файлу (типово для PR, що зачіпає тільки JS/TS-код).
|
|
95
|
+
|
|
96
|
+
## Залежності
|
|
97
|
+
|
|
98
|
+
### Зовнішні npm-пакети
|
|
99
|
+
|
|
100
|
+
Прямих імпортів з npm немає.
|
|
101
|
+
|
|
102
|
+
### Node.js вбудовані модулі
|
|
103
|
+
|
|
104
|
+
- `node:child_process` — імпорт `{ spawnSync }`. Використовується для синхронного запуску `npx stylelint ...`.
|
|
105
|
+
|
|
106
|
+
### Зовнішні бінарники / системні залежності
|
|
107
|
+
|
|
108
|
+
- `npx` — має бути в `PATH`. Це стандартний компаньйон `npm` / `bun` / `pnpm`.
|
|
109
|
+
- `stylelint` — має бути запускний через `npx` (через локальний `node_modules` або глобально). Конкретна версія й конфіг (`.stylelintrc*`) знаходяться поза межами цього модуля й керуються рівнем монорепо.
|
|
110
|
+
|
|
111
|
+
### Внутрішні модульні зв'язки
|
|
112
|
+
|
|
113
|
+
Сам файл нічого не імпортує з інших файлів проєкту. Натомість його імпортують:
|
|
114
|
+
|
|
115
|
+
- сусідній `tooling.mjs` (оркестратор правила `style-lint`),
|
|
116
|
+
- та/або тести в підтеці `tests/`.
|
|
117
|
+
|
|
118
|
+
## Потік виконання / Використання
|
|
119
|
+
|
|
120
|
+
### Типовий сценарій 1: quick-режим (локальний розробник)
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
import { lint } from './lint.mjs'
|
|
124
|
+
|
|
125
|
+
const changed = ['src/components/Button.vue', 'src/utils/dom.ts', 'src/styles/main.scss']
|
|
126
|
+
|
|
127
|
+
const code = await lint(changed)
|
|
128
|
+
process.exit(code)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Що відбудеться:
|
|
132
|
+
|
|
133
|
+
1. `filterStyleFiles(changed)` поверне `['src/components/Button.vue', 'src/styles/main.scss']`.
|
|
134
|
+
2. Сформується команда `npx stylelint --fix src/components/Button.vue src/styles/main.scss`.
|
|
135
|
+
3. `spawnSync` запустить `npx`, `stylelint` обробить тільки ці два файли, виправить що зможе, лог піде в консоль.
|
|
136
|
+
4. Функція поверне promise з exit-кодом `stylelint` (`0` — все добре; ненульовий — лишилися невиправні порушення або помилка конфігу).
|
|
137
|
+
|
|
138
|
+
### Типовий сценарій 2: ci-режим (повний прогін)
|
|
139
|
+
|
|
140
|
+
```js
|
|
141
|
+
import { lint } from './lint.mjs'
|
|
142
|
+
|
|
143
|
+
const code = await lint(undefined, process.cwd())
|
|
144
|
+
process.exit(code)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Що відбудеться:
|
|
148
|
+
|
|
149
|
+
1. `files === undefined`, тому в `args` додається літерал `**/*.{css,scss,vue}`.
|
|
150
|
+
2. Сформується команда `npx stylelint --fix '**/*.{css,scss,vue}'` (без shell-escaping — це аргумент).
|
|
151
|
+
3. `stylelint` сам розкриває glob від `cwd` і обходить весь проєкт.
|
|
152
|
+
4. Функція повертає його exit-код.
|
|
153
|
+
|
|
154
|
+
### Сценарій 3: quick-режим без жодного стильового файлу
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
const code = await lint(['README.md', 'src/index.ts'])
|
|
158
|
+
// code === 0, npx навіть не запускався
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Що відбудеться:
|
|
162
|
+
|
|
163
|
+
1. `filterStyleFiles` поверне `[]`.
|
|
164
|
+
2. Гілка `if (style.length === 0) return Promise.resolve(0)` поверне `0` миттєво.
|
|
165
|
+
3. Жодного дочірнього процесу не створюється — це швидкий «no-op».
|
|
166
|
+
|
|
167
|
+
### Як вписується в загальну архітектуру
|
|
168
|
+
|
|
169
|
+
Цей файл — реалізаційна одиниця «quick» кроку правила `style-lint`. Правило в монорепо має дві площини запуску:
|
|
170
|
+
|
|
171
|
+
- **quick** (швидкий) — викликається після зміни файлів локально, працює тільки по зміненому списку для мінімального часу відгуку.
|
|
172
|
+
- **ci** — викликається в неперервній інтеграції, проганяє по всьому glob-у щоб гарантовано перевірити весь репозиторій.
|
|
173
|
+
|
|
174
|
+
Файл `lint.mjs` уніфікує обидва режими в одній функції, де перемикач режиму — це `files === undefined` (ci) vs `files: string[]` (quick).
|
|
175
|
+
|
|
176
|
+
### Контракти й гарантії
|
|
177
|
+
|
|
178
|
+
- Функція `lint` **синхронно** виконує дочірній процес, але повертає `Promise<number>` — це навмисно, щоб уніфікувати інтерфейс з іншими «крок-функціями» в системі правил, які можуть бути по-справжньому асинхронні. Caller завжди робить `await lint(...)`.
|
|
179
|
+
- `lint` не кидає виключень: будь-який збій `npx` (включаючи відсутній бінарник) перетвориться в exit-код `1` через гілку `typeof r.status === 'number' ? r.status : 1`. Це робить функцію передбачуваною для оркестратора, який оперує тільки числовими кодами.
|
|
180
|
+
- `filterStyleFiles` — стабільна чиста функція, придатна для незалежного юніт-тестування (саме тому винесена як окремий експорт).
|
|
181
|
+
|
|
182
|
+
## Rebuild Test
|
|
183
|
+
|
|
184
|
+
Документація відповідає коду версії на момент написання: 35 рядків, два експорти (`filterStyleFiles`, `lint`), одна приватна регулярка (`STYLE_EXT_RE`), одна імпортована функція з `node:child_process` (`spawnSync`). Якщо файл буде переписано (наприклад, додасться третій експорт, зміниться сигнатура `lint`, з'явиться нова гілка для `--config`, або `spawnSync` буде замінено на асинхронний `spawn`), цей документ потребує перегенерації.
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# tooling.mjs
|
|
2
|
+
|
|
3
|
+
## Огляд
|
|
4
|
+
|
|
5
|
+
Модуль `tooling.mjs` реалізує **JS-частину перевірки правила `style-lint.mdc`** — тобто тих аспектів CSS/SCSS-лінтингу через `stylelint`, які **не вкриваються** Rego-політиками (`npx @nitra/cursor check`) і які потребують **файлової системи / cross-file** знання.
|
|
6
|
+
|
|
7
|
+
Конкретно перевіряє:
|
|
8
|
+
|
|
9
|
+
1. Наявність **конфігу stylelint** — або як поле `stylelint` у `package.json`, або як зовнішній файл (`.stylelintrc.json`, `.stylelintrc.js`, `stylelint.config.js`). Ця перевірка cross-file: треба порівняти, чи поле є, і якщо нема — чи є зовнішній файл.
|
|
10
|
+
2. Наявність файлу `.stylelintignore` у корені репозиторію.
|
|
11
|
+
3. Наявність workflow-файлу `.github/workflows/lint-style.yml` (структуру окремо валідовує rego-пакет `style_lint.lint_style_yml`).
|
|
12
|
+
|
|
13
|
+
Що **вже** покрила Rego (тому тут НЕ повторюється):
|
|
14
|
+
|
|
15
|
+
- `npm/policy/style_lint/package_json/` — наявність скрипта `lint-style` через `npx stylelint`, `@nitra/stylelint-config` у `devDependencies`, поле `stylelint.extends`.
|
|
16
|
+
- `npm/policy/style_lint/lint_style_yml/` — рядок `npx stylelint` у `run` workflow-файлу.
|
|
17
|
+
- `npm/policy/style_lint/vscode_extensions/` — `stylelint.vscode-stylelint` у `recommendations` файлу `.vscode/extensions.json`.
|
|
18
|
+
- `npm/policy/style_lint/vscode_settings/` — `css.validate`/`scss.validate`/`less.validate: false` у `.vscode/settings.json`.
|
|
19
|
+
|
|
20
|
+
JS-копії перевірок VS Code було **видалено**, щоб не було двох джерел істини — все, що може Rego, лишається тільки у Rego.
|
|
21
|
+
|
|
22
|
+
## Експорти / API
|
|
23
|
+
|
|
24
|
+
| Експорт | Тип | Призначення |
|
|
25
|
+
| ------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
26
|
+
| `check` | `async function (cwd?: string) => Promise<number>` | Основна точка входу: запускає всі перевірки конфігурації stylelint у заданому корені репозиторію та повертає exit-код (0 — OK, 1 — є проблеми). |
|
|
27
|
+
|
|
28
|
+
Внутрішня (НЕ експортується) функція:
|
|
29
|
+
|
|
30
|
+
| Функція | Призначення |
|
|
31
|
+
| --------------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
32
|
+
| `checkStylelintConfigPresence(reporter, cwd)` | Перевіряє наявність конфігурації stylelint (поле в `package.json` або зовнішній файл). |
|
|
33
|
+
|
|
34
|
+
## Функції
|
|
35
|
+
|
|
36
|
+
### `check(cwd?)`
|
|
37
|
+
|
|
38
|
+
**Сигнатура:**
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
export async function check(cwd = process.cwd()): Promise<number>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Параметри:**
|
|
45
|
+
|
|
46
|
+
- `cwd` (`string`, опціональний) — абсолютний шлях до кореня репозиторію, який треба перевірити. За замовчуванням використовується `process.cwd()` (поточна робоча директорія процесу).
|
|
47
|
+
|
|
48
|
+
**Повертає:**
|
|
49
|
+
|
|
50
|
+
- `Promise<number>` — exit-код процесу:
|
|
51
|
+
- `0` — усі перевірки пройдено (відсутні `fail`-події у репортера);
|
|
52
|
+
- `1` — хоч одна перевірка зафейлилась.
|
|
53
|
+
|
|
54
|
+
Конкретне значення береться з виклику `reporter.getExitCode()`, який інкапсульований у `createCheckReporter()`.
|
|
55
|
+
|
|
56
|
+
**Що робить:**
|
|
57
|
+
|
|
58
|
+
1. Створює репортер через `createCheckReporter()` — він збирає події `pass`/`fail` і виводить їх у консоль під час виконання.
|
|
59
|
+
2. Викликає `checkStylelintConfigPresence(reporter, cwd)` — перевірка №1 (конфіг stylelint).
|
|
60
|
+
3. Перевіряє наявність файлу `.stylelintignore` у корені:
|
|
61
|
+
- якщо є — звітує `pass('.stylelintignore існує')`;
|
|
62
|
+
- якщо нема — `fail('.stylelintignore не існує — створи з вмістом: dist/')`.
|
|
63
|
+
4. Перевіряє наявність workflow-файлу `.github/workflows/lint-style.yml`:
|
|
64
|
+
- якщо є — `pass` із зауваженням, що структуру файлу валідовує `npx @nitra/cursor fix → style_lint.lint_style_yml`;
|
|
65
|
+
- якщо нема — `fail` із вимогою його створити.
|
|
66
|
+
5. Повертає `reporter.getExitCode()`.
|
|
67
|
+
|
|
68
|
+
**Side effects:**
|
|
69
|
+
|
|
70
|
+
- Виконує **синхронні** виклики `existsSync` (читає файлову систему).
|
|
71
|
+
- Через репортер пише у консоль (stdout/stderr) повідомлення `pass`/`fail` (поведінка інкапсульована у `check-reporter.mjs`).
|
|
72
|
+
- Не змінює файли. Не виконує мережевих запитів. Не змінює стану процесу (не викликає `process.exit`) — повертає exit-код, а викликаюча сторона сама вирішує, як його використати.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### `checkStylelintConfigPresence(reporter, cwd)` _(внутрішня)_
|
|
77
|
+
|
|
78
|
+
**Сигнатура:**
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
async function checkStylelintConfigPresence(
|
|
82
|
+
reporter: CheckReporter,
|
|
83
|
+
cwd: string,
|
|
84
|
+
): Promise<void>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Параметри:**
|
|
88
|
+
|
|
89
|
+
- `reporter` (`CheckReporter`) — об'єкт-репортер, створений `createCheckReporter()`, з полями `{ pass, fail, getExitCode }`. У функції використовуються лише `pass` і `fail`.
|
|
90
|
+
- `cwd` (`string`) — корінь репозиторію.
|
|
91
|
+
|
|
92
|
+
**Повертає:**
|
|
93
|
+
|
|
94
|
+
- `Promise<void>` — нічого не повертає; результат виражається через виклики `reporter.pass(...)` / `reporter.fail(...)`.
|
|
95
|
+
|
|
96
|
+
**Логіка:**
|
|
97
|
+
|
|
98
|
+
1. Будує шлях до `package.json` через `join(cwd, 'package.json')`.
|
|
99
|
+
2. Якщо `package.json` **немає** — мовчки повертається з функції (`return`). Це означає: для тек без `package.json` перевірка пропускається (вона нерелевантна).
|
|
100
|
+
3. Читає `package.json` через `readFile(pkgPath, 'utf8')` і парсить як JSON.
|
|
101
|
+
4. Перевіряє `hasField` — `pkg.stylelint && typeof pkg.stylelint === 'object'` (саме поле-об'єкт; формат `extends: "@nitra/stylelint-config"` валідовує Rego).
|
|
102
|
+
5. Перевіряє `hasExternalCfg` — наявність хоча б одного з файлів:
|
|
103
|
+
- `.stylelintrc.json`
|
|
104
|
+
- `.stylelintrc.js`
|
|
105
|
+
- `stylelint.config.js`
|
|
106
|
+
6. Якщо `hasField || hasExternalCfg` — `pass('Конфіг stylelint є — у package.json або окремим файлом')`.
|
|
107
|
+
7. Інакше — `fail('Немає конфігу stylelint — додай "stylelint": { "extends": "@nitra/stylelint-config" } до package.json')`.
|
|
108
|
+
|
|
109
|
+
**Side effects:**
|
|
110
|
+
|
|
111
|
+
- Синхронно: `existsSync` для `package.json` та для трьох можливих зовнішніх конфіг-файлів.
|
|
112
|
+
- Асинхронно: `readFile` для `package.json`.
|
|
113
|
+
- Через репортер пише до консолі результат.
|
|
114
|
+
- Може кинути виняток, якщо `package.json` існує, але містить невалідний JSON (`JSON.parse` кине `SyntaxError`) — функція **не** обробляє цю помилку.
|
|
115
|
+
|
|
116
|
+
**Зауваження щодо файлів-конфігів:**
|
|
117
|
+
|
|
118
|
+
Список перевірюваних зовнішніх конфігів **не** охоплює всі можливі формати, які підтримує stylelint (наприклад, `.stylelintrc`, `.stylelintrc.yaml`, `.stylelintrc.yml`, `.stylelintrc.cjs`). Перевіряються лише три найпопулярніші: `.stylelintrc.json`, `.stylelintrc.js`, `stylelint.config.js`.
|
|
119
|
+
|
|
120
|
+
## Залежності
|
|
121
|
+
|
|
122
|
+
### Імпорти із Node.js
|
|
123
|
+
|
|
124
|
+
| Модуль | Що використовується |
|
|
125
|
+
| ------------------ | --------------------------------------------------- |
|
|
126
|
+
| `node:fs` | `existsSync` — синхронна перевірка існування файлу. |
|
|
127
|
+
| `node:fs/promises` | `readFile` — асинхронне читання файлу як рядка. |
|
|
128
|
+
| `node:path` | `join` — крос-платформне склеювання шляхів. |
|
|
129
|
+
|
|
130
|
+
### Внутрішні імпорти
|
|
131
|
+
|
|
132
|
+
| Шлях | Що дає |
|
|
133
|
+
| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
134
|
+
| `../../../scripts/lib/check-reporter.mjs` | `createCheckReporter()` — фабрика репортера, який має методи `pass(msg)`, `fail(msg)` та `getExitCode()`. Тип `CheckReporter` тягнеться JSDoc-посиланням `import('../../../scripts/lib/check-reporter.mjs').CheckReporter`. |
|
|
135
|
+
|
|
136
|
+
### Зв'язані артефакти (НЕ імпортуються, але важливі контекстно)
|
|
137
|
+
|
|
138
|
+
- `npm/rules/style-lint/style-lint.mdc` — людино-зрозуміле формулювання правила.
|
|
139
|
+
- `npm/policy/style_lint/package_json/` — Rego-пакет, що покриває валідацію формату полів `package.json`.
|
|
140
|
+
- `npm/policy/style_lint/lint_style_yml/` — Rego-пакет, що валідовує вміст workflow-файлу.
|
|
141
|
+
- `npm/policy/style_lint/vscode_extensions/` — Rego для `.vscode/extensions.json`.
|
|
142
|
+
- `npm/policy/style_lint/vscode_settings/` — Rego для `.vscode/settings.json`.
|
|
143
|
+
|
|
144
|
+
## Потік виконання / Використання
|
|
145
|
+
|
|
146
|
+
### Контекст виклику
|
|
147
|
+
|
|
148
|
+
Модуль є частиною ланцюжка перевірок правил `@nitra/cursor`. Експортована функція `check` викликається диспетчером перевірок (зазвичай через CLI `npx @nitra/cursor check`), який ітерує rule-теки і для кожної шукає файл `js/tooling.mjs` з експортованим `check`.
|
|
149
|
+
|
|
150
|
+
### Послідовність дій усередині `check`
|
|
151
|
+
|
|
152
|
+
1. **Створення репортера:**
|
|
153
|
+
```js
|
|
154
|
+
const reporter = createCheckReporter()
|
|
155
|
+
const { pass, fail } = reporter
|
|
156
|
+
```
|
|
157
|
+
(`pass`/`fail` деструктуруються, але в `check` напряму не використовуються — лише як алії; всередині `checkStylelintConfigPresence` вони беруться зі свого деструктурування.)
|
|
158
|
+
2. **Перевірка конфігу stylelint** — `await checkStylelintConfigPresence(reporter, cwd)`.
|
|
159
|
+
3. **Перевірка `.stylelintignore`** — `existsSync(join(cwd, '.stylelintignore'))`.
|
|
160
|
+
4. **Перевірка workflow `lint-style.yml`** — `existsSync(join(cwd, '.github/workflows/lint-style.yml'))`.
|
|
161
|
+
5. **Повернення exit-коду** — `return reporter.getExitCode()`.
|
|
162
|
+
|
|
163
|
+
### Приклад використання
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
import { check } from '@nitra/cursor/rules/style-lint/js/tooling.mjs'
|
|
167
|
+
|
|
168
|
+
const exitCode = await check(process.cwd())
|
|
169
|
+
process.exit(exitCode)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Або через CLI-обгортку:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npx @nitra/cursor check
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
(CLI сам знайде цей модуль за конвенцією `npm/rules/<rule>/js/tooling.mjs` і викличе `check()` без аргументів, тож буде використано `process.cwd()`.)
|
|
179
|
+
|
|
180
|
+
### Гарантії та межі відповідальності
|
|
181
|
+
|
|
182
|
+
- Модуль **не змінює** файли (немає `fix`-режиму) — він тільки **репортує**.
|
|
183
|
+
- Він **не дублює** перевірок, які вже робить Rego. Розділення: FS / cross-file → JS (тут); формат / структура одного файлу → Rego.
|
|
184
|
+
- Виклик `check` із `cwd`, де немає `package.json`, — валідний сценарій: перевірка конфігу stylelint буде пропущена (мовчки), решта перевірок (`.stylelintignore`, workflow) — виконається.
|
|
185
|
+
- Якщо `package.json` містить невалідний JSON — функція впаде з `SyntaxError` (це не пере́хоплюється навмисно: гнилий JSON — це самостійна проблема, яку треба чути одразу).
|
|
186
|
+
|
|
187
|
+
## Rebuild Test
|
|
188
|
+
|
|
189
|
+
З цього документа можна повністю відновити поведінку файлу:
|
|
190
|
+
|
|
191
|
+
- Знаючи список перевірок (конфіг stylelint, `.stylelintignore`, `lint-style.yml`), повідомлення `pass`/`fail` і допустимі імена файлів-конфігів — реалізація відтворюється 1:1.
|
|
192
|
+
- Деталі контракту функцій (типи параметрів, тип повернення, side effects, поведінка за відсутності `package.json`) описані явно.
|
|
193
|
+
- Експорти та їх кількість (єдиний експорт `check`) зафіксовано.
|
|
194
|
+
- Імпорти Node-модулів і внутрішні залежності перераховано вичерпно.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# fix.mjs — entry-point правила `tauri`
|
|
2
|
+
|
|
3
|
+
## Огляд
|
|
4
|
+
|
|
5
|
+
Файл `npm/rules/tauri/fix.mjs` — це тонкий **entry-point** (точка входу) правила `tauri` у системі правил `@nitra/cursor`. Файл виконує дві ролі одночасно:
|
|
6
|
+
|
|
7
|
+
1. **Library mode** — експортує функцію `run(ctx)`, яку оркестратор CLI (`@nitra/cursor`) викликає через динамічний `import`, передаючи спільний контекст прогону (`RuleContext`, наприклад, `walkCache` для повторного використання обходу файлової системи між правилами).
|
|
8
|
+
2. **Standalone mode** — якщо файл запущено напряму через `bun npm/rules/tauri/fix.mjs`, виконується повний еквівалент команди `npx @nitra/cursor fix tauri` (з підвантаженням конфігу, обробкою whitelist та виведенням summary), а процес завершується з відповідним exit-code для CI/IDE.
|
|
9
|
+
|
|
10
|
+
Сам файл **не містить жодної доменної логіки правила** `tauri` — уся робота (steps `applies → JS-concerns → policy → mdc-refs`) делегується у бібліотечну функцію `runStandardRule()`. Цей файл лише підключає стандартний раннер до конкретної директорії правила (`import.meta.dirname`) і опціонально запускає CLI-обгортку.
|
|
11
|
+
|
|
12
|
+
Файл є **типовим шаблоном `fix.mjs`** для будь-якого правила в `npm/rules/<id>/`: майже всі правила в цій директорії мають ідентичний за структурою `fix.mjs`, що відрізняється лише доменом (`tauri`, `vue`, `python` тощо), який неявно визначається через шлях `import.meta.dirname`.
|
|
13
|
+
|
|
14
|
+
## Експорти / API
|
|
15
|
+
|
|
16
|
+
| Експорт | Тип | Опис |
|
|
17
|
+
| ------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
18
|
+
| `run` | `(ctx?: RuleContext) => Promise<number>` | Іменований експорт. Запускає стандартний пайплайн правила (`applies → JS-concerns → policy → mdc-refs`) для директорії, у якій знаходиться `fix.mjs`. Повертає `0` при відсутності порушень і `1` (або інший ненульовий код) у разі порушень. |
|
|
19
|
+
|
|
20
|
+
Файл **не має** `default`-експорту. Side-effect на верхньому рівні: якщо модуль завантажено як CLI-entry (`isRunAsCli(import.meta.url) === true`), виконується `await runRuleCli(...)` і `process.exit(...)`.
|
|
21
|
+
|
|
22
|
+
### Тип `RuleContext`
|
|
23
|
+
|
|
24
|
+
Тип параметра `ctx` імпортується (через JSDoc `@typedef`) з `../../scripts/lib/run-standard-rule.mjs`. Зазвичай містить:
|
|
25
|
+
|
|
26
|
+
- `walkCache` — кеш обходу файлової системи, щоб не сканувати дерево повторно для кожного правила.
|
|
27
|
+
- Інші поля, специфічні для оркестрації (логер, прапорці `dryRun`, тощо).
|
|
28
|
+
|
|
29
|
+
Параметр `ctx` опціональний: якщо файл запущено окремо (standalone), `ctx` буде `undefined`, і `runStandardRule()` сам створить локальний контекст.
|
|
30
|
+
|
|
31
|
+
## Функції
|
|
32
|
+
|
|
33
|
+
### `run(ctx)`
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
export function run(ctx) {
|
|
37
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- **Сигнатура:** `function run(ctx?: RuleContext): Promise<number>`
|
|
42
|
+
- **Параметри:**
|
|
43
|
+
- `ctx` _(опціональний, `RuleContext`)_ — контекст прогону, який зазвичай передає оркестратор `@nitra/cursor`. У ньому, серед іншого, може бути `walkCache` для уникнення повторного сканування файлової системи між різними правилами.
|
|
44
|
+
- **Повертає:** `Promise<number>` — асинхронний код виходу:
|
|
45
|
+
- `0` — правило відпрацювало без порушень (OK);
|
|
46
|
+
- `1` (або інший ненульовий код, який повертає `runStandardRule`) — знайдено порушення.
|
|
47
|
+
- **Side effects:**
|
|
48
|
+
- Викликає `runStandardRule()`, яка послідовно виконує етапи `applies → JS-concerns → policy → mdc-refs`. Ці етапи можуть:
|
|
49
|
+
- читати файли у репозиторії;
|
|
50
|
+
- запускати JS-перевірки (наприклад, статичні правила з директорії `js/`);
|
|
51
|
+
- виконувати policy-перевірки (наприклад, `policy/`-перевірки правила `tauri`);
|
|
52
|
+
- порівнювати посилання у `.mdc`-файлах (`mdc-refs`).
|
|
53
|
+
- Сам по собі `run()` **не змінює** файли (правило `fix`-типу може здійснювати автозаміни всередині `runStandardRule`, якщо це закладено у бібліотеці; у самому `fix.mjs` цієї логіки немає).
|
|
54
|
+
- **Як використовується:** оркестратор CLI імпортує `fix.mjs` правила і викликає `await run(ctx)`. Результат складається у загальний summary прогону.
|
|
55
|
+
|
|
56
|
+
### Standalone-блок (top-level)
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
if (isRunAsCli(import.meta.url)) {
|
|
60
|
+
// eslint-disable-next-line n/no-process-exit, unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
61
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- **Призначення:** дозволяє запускати правило напряму, без проходження через головний CLI `@nitra/cursor`. Команда `bun npm/rules/tauri/fix.mjs` стає повним еквівалентом `npx @nitra/cursor fix tauri`.
|
|
66
|
+
- **Логіка:**
|
|
67
|
+
- `isRunAsCli(import.meta.url)` повертає `true`, якщо поточний модуль є точкою входу процесу (а не imported-модулем). Це класична перевірка ESM-еквівалента `require.main === module`.
|
|
68
|
+
- Якщо `true`, викликається `runRuleCli(import.meta.dirname)`, яка обгортає `runStandardRule` додатковою CLI-логікою: завантаження конфігу проєкту, обробка whitelist (виключень), виведення summary у консоль.
|
|
69
|
+
- `process.exit(...)` із цим кодом — обов’язковий для CI/IDE: процес має повернути ненульовий код у разі порушень, щоб pipeline (наприклад, у `n-cursor` чи у GitHub Actions) міг це задетектити. Тому ESLint-правила `n/no-process-exit` і `unicorn/no-process-exit` навмисно вимкнено через inline-коментар.
|
|
70
|
+
- **Side effects:**
|
|
71
|
+
- Може писати у `stdout`/`stderr` (summary, помилки).
|
|
72
|
+
- Завершує процес викликом `process.exit(...)` — після цього рядка код не виконується.
|
|
73
|
+
- **Не виконується** у library mode (коли файл імпортовано іншим скриптом).
|
|
74
|
+
|
|
75
|
+
## Залежності
|
|
76
|
+
|
|
77
|
+
### Внутрішні (relative imports)
|
|
78
|
+
|
|
79
|
+
| Імпорт | Шлях | Призначення |
|
|
80
|
+
| ----------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
81
|
+
| `isRunAsCli` | `../../scripts/lib/run-rule-cli.mjs` | Утиліта-перевірка: чи запущено файл як головний модуль (entry-point), а не як `import`. |
|
|
82
|
+
| `runRuleCli` | `../../scripts/lib/run-rule-cli.mjs` | Standalone-обгортка над `runStandardRule`: завантаження конфігу, whitelist, summary, exit-code. |
|
|
83
|
+
| `runStandardRule` | `../../scripts/lib/run-standard-rule.mjs` | Бібліотечна функція, що виконує стандартний пайплайн правила: `applies → JS-concerns → policy → mdc-refs`. |
|
|
84
|
+
|
|
85
|
+
Усі шляхи відносні: `../../scripts/lib/` → `npm/scripts/lib/`.
|
|
86
|
+
|
|
87
|
+
### Зовнішні
|
|
88
|
+
|
|
89
|
+
Файл **не має** прямих залежностей від npm-пакетів. Усі npm-залежності, якщо такі є, прихилені всередині бібліотечних функцій (`runStandardRule`, `runRuleCli`).
|
|
90
|
+
|
|
91
|
+
### Контекст домену
|
|
92
|
+
|
|
93
|
+
Директорія `npm/rules/tauri/` містить також:
|
|
94
|
+
|
|
95
|
+
- `tauri.mdc` — людиночитна специфікація правила (формат Cursor `.mdc`);
|
|
96
|
+
- `meta.json` — метадані правила (наприклад, прапорці `worktree`, опис);
|
|
97
|
+
- `js/` — JS-частина перевірок правила (запускається на етапі JS-concerns);
|
|
98
|
+
- `policy/` — policy-перевірки (rego/інші) на етапі policy.
|
|
99
|
+
|
|
100
|
+
`runStandardRule` неявно «знає», як обробити кожен з цих артефактів, через переданий `import.meta.dirname`.
|
|
101
|
+
|
|
102
|
+
## Потік виконання / Використання
|
|
103
|
+
|
|
104
|
+
### Library mode (типовий, через оркестратор)
|
|
105
|
+
|
|
106
|
+
1. Користувач запускає `npx @nitra/cursor fix` (або підкоманду, що зачіпає правило `tauri`).
|
|
107
|
+
2. Оркестратор `@nitra/cursor`:
|
|
108
|
+
1. Знаходить директорію `npm/rules/tauri/`.
|
|
109
|
+
2. Виконує `const mod = await import('npm/rules/tauri/fix.mjs')`.
|
|
110
|
+
3. Перевірка `isRunAsCli(import.meta.url)` повертає `false` (бо це import, а не entry-point) — standalone-блок **не виконується**.
|
|
111
|
+
4. Викликає `await mod.run(ctx)`, передаючи спільний контекст (з `walkCache` тощо).
|
|
112
|
+
3. `run(ctx)` → `runStandardRule(import.meta.dirname, ctx)` → послідовно виконуються етапи:
|
|
113
|
+
- **applies** — фільтрація: чи правило взагалі застосовне до поточного репозиторію/файлів.
|
|
114
|
+
- **JS-concerns** — JS-перевірки з директорії `js/` правила.
|
|
115
|
+
- **policy** — policy-перевірки з директорії `policy/` правила.
|
|
116
|
+
- **mdc-refs** — перевірка посилань у `.mdc` файлах правила.
|
|
117
|
+
4. Повертається `Promise<number>` із кодом виходу для цього правила, який оркестратор агрегує у summary всіх правил.
|
|
118
|
+
|
|
119
|
+
### Standalone mode (debug / прямий запуск)
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
bun npm/rules/tauri/fix.mjs
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
1. Bun завантажує файл як головний модуль.
|
|
126
|
+
2. `import { isRunAsCli, runRuleCli, runStandardRule }` — підвантажуються залежності.
|
|
127
|
+
3. Експорт `run` стає доступним (але ніхто його не викликає у цьому режимі).
|
|
128
|
+
4. Виконується top-level `if (isRunAsCli(import.meta.url))`:
|
|
129
|
+
- `isRunAsCli(...) === true`.
|
|
130
|
+
- `await runRuleCli(import.meta.dirname)`:
|
|
131
|
+
- завантажує конфіг проєкту;
|
|
132
|
+
- застосовує whitelist;
|
|
133
|
+
- всередині викликає `runStandardRule(dir, ctx)` (з локально-створеним контекстом);
|
|
134
|
+
- виводить summary у консоль.
|
|
135
|
+
- `process.exit(<code>)` — процес завершується з кодом `0` (OK) або `1` (порушення).
|
|
136
|
+
|
|
137
|
+
### Дві ролі одного файлу
|
|
138
|
+
|
|
139
|
+
Архітектурний прийом — **«library + main» в одному файлі** — закладений у коментарі коду:
|
|
140
|
+
|
|
141
|
+
> Дві ролі fix.mjs: library (run) + standalone (main).
|
|
142
|
+
|
|
143
|
+
Це дозволяє:
|
|
144
|
+
|
|
145
|
+
- розробнику швидко налагоджувати правило окремо (`bun rules/tauri/fix.mjs`);
|
|
146
|
+
- оркестратору повторно використовувати кеш обходу (`walkCache`) між правилами під час масового прогону.
|
|
147
|
+
|
|
148
|
+
## Rebuild Test
|
|
149
|
+
|
|
150
|
+
Файл є **тонким адаптером** і не містить доменної логіки — його можна повністю відтворити за цією документацією. Структура:
|
|
151
|
+
|
|
152
|
+
1. Два іменовані імпорти з `../../scripts/lib/run-rule-cli.mjs`: `isRunAsCli`, `runRuleCli`.
|
|
153
|
+
2. Один іменований імпорт з `../../scripts/lib/run-standard-rule.mjs`: `runStandardRule`.
|
|
154
|
+
3. JSDoc-блок із описом, типом параметра `ctx` (через `@param {import('...')...}`) і типом результату (`Promise<number>`).
|
|
155
|
+
4. `export function run(ctx) { return runStandardRule(import.meta.dirname, ctx) }`.
|
|
156
|
+
5. Top-level `if (isRunAsCli(import.meta.url))` з викликом `process.exit(await runRuleCli(import.meta.dirname))` і inline-коментарем-вимкненням ESLint-правил `n/no-process-exit` та `unicorn/no-process-exit`.
|
|
157
|
+
|
|
158
|
+
Жодних інших артефактів (інших експортів, констант, побічних `console.log`, мутації глобального стану) у файлі немає.
|