@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.
- package/.claude-template/settings.template.json +2 -2
- package/.pi-template/extensions/n-cursor-adr/docs/index.md +13 -24
- package/CHANGELOG.md +21 -0
- package/bin/n-cursor.js +47 -24
- package/lib/docs/models.md +29 -18
- package/lib/docs/omlx-trace.md +51 -0
- package/lib/docs/omlx.md +31 -15
- package/lib/omlx.mjs +2 -5
- package/package.json +1 -1
- package/rules/abie/docs/fix.md +17 -11
- package/rules/adr/docs/fix.md +25 -140
- package/rules/bun/docs/fix.md +18 -151
- package/rules/capacitor/docs/fix.md +16 -13
- package/rules/capacitor/js/docs/platforms.md +31 -43
- package/rules/changelog/docs/fix.md +25 -169
- package/rules/ci4/docs/fix.md +11 -14
- package/rules/doc-files/doc-files.mdc +60 -0
- package/rules/doc-files/docs/fix.md +31 -0
- package/rules/doc-files/fix.mjs +19 -0
- package/{skills → rules}/doc-files/js/docgen-extract.mjs +42 -19
- package/{skills → rules}/doc-files/js/docgen-files-batch.mjs +18 -5
- package/{skills → rules}/doc-files/js/docgen-gen.mjs +46 -5
- package/{skills → rules}/doc-files/js/docgen-ignore.mjs +2 -1
- package/{skills → rules}/doc-files/js/docgen-scan.mjs +11 -3
- package/{skills → rules}/doc-files/js/docs/docgen-crc.md +1 -1
- package/{skills → rules}/doc-files/js/docs/docgen-extract-anchors.md +1 -1
- package/{skills → rules}/doc-files/js/docs/docgen-extract.md +2 -2
- package/{skills → rules}/doc-files/js/docs/docgen-files-batch.md +2 -2
- package/{skills → rules}/doc-files/js/docs/docgen-gen.md +2 -2
- package/{skills → rules}/doc-files/js/docs/docgen-ignore.md +4 -4
- package/rules/doc-files/js/docs/docgen-prompts.md +39 -0
- package/rules/doc-files/js/docs/docgen-scan.md +54 -0
- package/rules/doc-files/js/docs/lint.md +36 -0
- package/rules/doc-files/js/docs/units-js.md +31 -0
- package/rules/doc-files/js/docs/units-rs.md +35 -0
- package/rules/doc-files/js/docs/units.md +30 -0
- package/rules/doc-files/js/lint.mjs +96 -0
- package/{skills → rules}/doc-files/js/units-rs.mjs +37 -17
- package/rules/doc-files/lint/docs/lint.md +37 -0
- package/rules/doc-files/lint/lint.mjs +105 -0
- package/rules/doc-files/meta.json +1 -0
- package/rules/docker/docs/fix.md +21 -161
- package/rules/efes/docs/fix.md +23 -194
- package/rules/feedback/docs/fix.md +10 -8
- package/rules/ga/docs/fix.md +10 -5
- package/rules/ga/meta.json +1 -1
- package/rules/graphql/docs/fix.md +23 -119
- package/rules/hasura/docs/fix.md +19 -5
- package/rules/hasura/js/docs/internal_urls.md +34 -307
- package/rules/image-avif/docs/fix.md +16 -127
- package/rules/image-compress/docs/fix.md +20 -141
- package/rules/image-compress/js/docs/package_setup.md +22 -182
- package/rules/js-bun-db/docs/fix.md +23 -139
- package/rules/js-bun-db/js/docs/safety.md +33 -221
- package/rules/js-bun-redis/docs/fix.md +25 -114
- package/rules/js-bun-redis/js/docs/imports.md +18 -166
- package/rules/js-lint/docs/fix.md +30 -108
- package/rules/js-lint/js/docs/lint-findings.md +37 -17
- package/rules/js-lint/js/docs/lint.md +22 -238
- package/rules/js-lint/js/docs/tooling.md +34 -331
- package/rules/js-lint/js/lint.mjs +19 -12
- package/rules/js-lint/js-lint.mdc +1 -1
- package/rules/js-lint/meta.json +1 -1
- package/rules/js-lint-ci/docs/fix.md +16 -149
- package/rules/js-lint-ci/js/docs/lint.md +16 -136
- package/rules/js-lint-ci/js-lint-ci.mdc +1 -1
- package/rules/js-lint-ci/meta.json +1 -1
- package/rules/js-mssql/docs/fix.md +18 -123
- package/rules/js-mssql/js/docs/deps.md +28 -251
- package/rules/js-run/docs/fix.md +23 -138
- package/rules/js-run/js/docs/runtime.md +24 -378
- package/rules/k8s/docs/fix.md +18 -123
- package/rules/nginx-default-tpl/docs/fix.md +22 -118
- package/rules/nginx-default-tpl/js/docs/template.md +38 -360
- package/rules/npm-module/docs/fix.md +27 -89
- package/rules/npm-module/js/docs/header_doc_pointer.md +15 -15
- package/rules/npm-module/js/docs/package_structure.md +36 -258
- package/rules/npm-module/js/docs/rule_meta.md +25 -127
- package/rules/npm-module/js/docs/skill_meta.md +18 -180
- package/rules/npm-module/js/rule_meta.mjs +3 -3
- package/rules/php/docs/fix.md +21 -98
- package/rules/php/js/docs/tooling.md +20 -143
- package/rules/python/docs/fix.md +25 -157
- package/rules/python/js/docs/applies.md +20 -98
- package/rules/python/js/docs/tooling.md +27 -144
- package/rules/rego/docs/fix.md +24 -112
- package/rules/rego/js/docs/applies.md +20 -164
- package/rules/rego/js/docs/lint.md +15 -110
- package/rules/rego/meta.json +1 -1
- package/rules/release/docs/fix.md +16 -114
- package/rules/rust/docs/fix.md +24 -119
- package/rules/rust/js/docs/applies.md +20 -129
- package/rules/security/docs/fix.md +21 -78
- package/rules/security/js/docs/sample_secret.md +23 -182
- package/rules/security/js/docs/trufflehog.md +19 -128
- package/rules/security/meta.json +1 -1
- package/rules/style-lint/docs/fix.md +16 -150
- package/rules/style-lint/js/docs/lint.md +21 -172
- package/rules/style-lint/js/docs/tooling.md +19 -184
- package/rules/style-lint/js/lint.mjs +4 -3
- package/rules/style-lint/meta.json +1 -1
- package/rules/tauri/docs/fix.md +26 -152
- package/rules/tauri/js/docs/cargo_mutants_config.md +21 -159
- package/rules/tauri/js/docs/tooling.md +20 -217
- package/rules/test/docs/fix.md +19 -127
- package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +15 -127
- package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +17 -153
- package/rules/test/js/docs/cargo_mutants_config.md +24 -164
- package/rules/test/js/docs/location.md +24 -126
- package/rules/test/js/docs/no-process-chdir.md +20 -151
- package/rules/test/js/docs/no-relative-fs-path.md +24 -261
- package/rules/test/js/docs/stryker_config.md +48 -148
- package/rules/test/js/docs/vitest-config-pool-forks.md +21 -164
- package/rules/text/docs/fix.md +25 -113
- package/rules/text/js/docs/forbidden-prettier.md +21 -132
- package/rules/text/js/docs/formatting.md +60 -251
- package/rules/text/js/docs/lint.md +17 -114
- package/rules/text/js/lint.mjs +5 -3
- package/rules/text/lint/docs/lint.md +1 -1
- package/rules/text/lint/docs/run-dotenv-linter.md +1 -1
- package/rules/text/lint/docs/run-shellcheck.md +1 -1
- package/rules/text/lint/lint.mjs +13 -9
- package/rules/text/lint/run-dotenv-linter.mjs +13 -10
- package/rules/text/lint/run-shellcheck.mjs +10 -6
- package/rules/text/meta.json +1 -1
- package/rules/vue/docs/fix.md +25 -118
- package/rules/vue/js/docs/packages.md +25 -323
- package/rules/worktree/docs/fix.md +31 -150
- package/scripts/coverage-classify/docs/index.md +23 -209
- package/scripts/coverage-classify/docs/verdict-schema.md +14 -159
- package/scripts/dispatcher/docs/trace.md +35 -0
- package/scripts/docs/auto-rules.md +37 -361
- package/scripts/docs/lint-cli.md +12 -13
- package/scripts/docs/post-tool-use-fix.md +16 -15
- package/scripts/docs/skills-cli.md +26 -23
- package/scripts/docs/sync-claude-config.md +94 -34
- package/scripts/docs/worktree-cli.md +11 -34
- package/scripts/lib/docs/assert-project-root.md +14 -16
- package/scripts/lib/docs/changed-files.md +24 -139
- package/scripts/lib/docs/discover-check-rules-from-cursor.md +14 -146
- package/scripts/lib/docs/rule-meta.md +1 -1
- package/scripts/lib/docs/rule-predicates.md +20 -17
- package/scripts/lib/docs/run-rule-cli.md +14 -18
- package/scripts/lib/docs/run-rule.md +13 -20
- package/scripts/lib/docs/run-standard-rule.md +12 -15
- package/scripts/lib/docs/sync-gitignore-worktree.md +15 -18
- package/scripts/lib/rule-meta.mjs +10 -6
- package/scripts/lib/rule-predicates.mjs +1 -1
- package/scripts/lint-cli.mjs +28 -20
- package/scripts/sync-claude-config.mjs +4 -1
- package/scripts/utils/docs/with-lock.md +19 -12
- package/scripts/utils/with-lock.mjs +4 -2
- package/skills/doc-aggregate/SKILL.md +2 -2
- package/skills/doc-aggregate/js/docgen-ignore.mjs +6 -6
- package/skills/doc-aggregate/js/docs/docgen-ignore.md +1 -1
- package/skills/doc-aggregate/js/docs/docgen-scan.md +78 -0
- package/skills/doc-files/.changes/260612-0031.md +5 -0
- package/skills/doc-files/.changes/260612-0036.md +5 -0
- package/skills/doc-files/.changes/260612-0114.md +5 -0
- package/skills/doc-files/SKILL.md +6 -6
- package/skills/fix/js/docs/llm-worker.md +17 -15
- package/skills/fix/js/docs/orchestrator.md +30 -23
- package/skills/fix/js/docs/t0.md +26 -16
- package/skills/start-check/js/docs/check.md +26 -22
- package/skills/taze/js/docs/diff.md +44 -20
- package/skills/doc-files/js/docs/docgen-prompts.md +0 -32
- package/skills/doc-files/js/docs/docgen-scan.md +0 -25
- package/skills/doc-files/js/docs/units-rs.md +0 -35
- /package/{skills → rules}/doc-files/js/docgen-crc.mjs +0 -0
- /package/{skills → rules}/doc-files/js/docgen-extract-anchors.mjs +0 -0
- /package/{skills → rules}/doc-files/js/docgen-prompts.mjs +0 -0
- /package/{skills → rules}/doc-files/js/units-js.mjs +0 -0
- /package/{skills → rules}/doc-files/js/units.mjs +0 -0
|
@@ -1,335 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
docgen:
|
|
3
|
+
source: npm/rules/vue/js/packages.mjs
|
|
4
|
+
crc: 6119ae9c
|
|
5
|
+
score: 85
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# packages.mjs
|
|
2
9
|
|
|
3
10
|
## Огляд
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- наявність та коректність `src/vite-env.d.ts` із triple-slash-посиланням на `vite/client`;
|
|
8
|
-
- наявність `jsconfig.json` у корені пакета;
|
|
9
|
-
- наявність та коректне конфігурування `vite.config.{js,ts,mjs}` (зокрема `VueMacros`, `AutoImport` і Bun-сумісність);
|
|
10
|
-
- наявність `'vue'` у списку `imports` плагіна `unplugin-auto-import` (`AutoImport`);
|
|
11
|
-
- відсутність заборонених явних value-імпортів з `'vue'` у джерелах пакета (скан через oxc-parser у сусідньому модулі);
|
|
12
|
-
- відсутність імпортів Node-нативних модулів (`node:*` або bare-ім’я кшталту `fs`, `path`) у `.vue` SFC;
|
|
13
|
-
- відсутність згадок `esbuild` у джерелах пакета (заохочується перехід на `rolldown`);
|
|
14
|
-
- наявність рекомендації розширення `Vue.volar` у `.vscode/extensions.json` на рівні всього репозиторію.
|
|
15
|
-
|
|
16
|
-
Перевірка залежностей `package.json` (`vite >= 8`, `@vitejs/plugin-vue`, `vue-macros`, `unplugin-auto-import`, `vite-plugin-vue-layouts-next`, заборона `esbuild`) виноситься у policy `vue.package_json` і викликається через CLI `npx @nitra/cursor fix`; цей модуль лише друкує підказку про це.
|
|
17
|
-
|
|
18
|
-
Результати збираються через `createCheckReporter()` і повертаються у вигляді exit-коду: `0` — все OK, `1` — є проблеми. Основна публічна точка входу — функція `check(cwd)`.
|
|
19
|
-
|
|
20
|
-
## Експорти / API
|
|
21
|
-
|
|
22
|
-
Модуль є ES-модулем (`*.mjs`) і має такі іменовані експорти:
|
|
23
|
-
|
|
24
|
-
- `isVueComponentLibraryPkg(pkg)` — predicate, що визначає, чи є пакет бібліотекою компонентів Vue (за наявністю `vue` у `peerDependencies`).
|
|
25
|
-
- `check(cwd?)` — головна функція перевірки усього репозиторію; повертає `Promise<number>` із exit-кодом.
|
|
26
|
-
|
|
27
|
-
Решта функцій модуля — приватні (file-local) helpers, які використовуються лише всередині `packages.mjs`.
|
|
28
|
-
|
|
29
|
-
## Функції
|
|
30
|
-
|
|
31
|
-
### `isEsbuildScanFile(relPosix)`
|
|
32
|
-
|
|
33
|
-
- **Сигнатура:** `function isEsbuildScanFile(relPosix: string): boolean`
|
|
34
|
-
- **Параметри:**
|
|
35
|
-
- `relPosix` — відносний шлях у POSIX-форматі (з прямими слешами), відраховуваний від кореня пакета.
|
|
36
|
-
- **Повертає:** `boolean` — `true`, якщо файл варто перевіряти на текстові згадки `esbuild`, інакше `false`.
|
|
37
|
-
- **Логіка:** виключає типові службові каталоги (`node_modules/`, `dist/`, `build/`, `coverage/`, `.git/`), типові lock-файли (`bun.lock`, `bun.lockb`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`), і допускає лише розширення з білого списку: `.js`, `.mjs`, `.cjs`, `.ts`, `.tsx`, `.vue`, `.json`, `.jsonc`, `.yaml`, `.yml`, `.md`, `.mdc`.
|
|
38
|
-
- **Side effects:** немає.
|
|
39
|
-
|
|
40
|
-
### `appendEsbuildLineMatches(rel, content, matches, maxMatches)`
|
|
41
|
-
|
|
42
|
-
- **Сигнатура:** `function appendEsbuildLineMatches(rel: string, content: string, matches: { rel: string; line: number; snippet: string }[], maxMatches: number): void`
|
|
43
|
-
- **Параметри:**
|
|
44
|
-
- `rel` — відносний шлях до файлу (для повідомлень).
|
|
45
|
-
- `content` — повний вміст файлу як рядок.
|
|
46
|
-
- `matches` — мутабельний буфер, у який дописуються знайдені збіги.
|
|
47
|
-
- `maxMatches` — верхня межа кількості елементів у `matches`; при досягненні функція припиняє обробку.
|
|
48
|
-
- **Повертає:** `void`. Результат повертається через мутацію аргументу `matches`.
|
|
49
|
-
- **Логіка:** розбиває `content` на рядки, перевіряє регулярний вираз `\besbuild\b` і додає об’єкт `{ rel, line: i + 1, snippet: line.trim() }` для кожного збігу.
|
|
50
|
-
- **Side effects:** мутує переданий масив `matches`.
|
|
51
|
-
|
|
52
|
-
### `collectEsbuildMatchesInFiles(absPackageRoot, files, maxMatches)`
|
|
53
|
-
|
|
54
|
-
- **Сигнатура:** `async function collectEsbuildMatchesInFiles(absPackageRoot: string, files: { rel: string }[], maxMatches: number): Promise<{ rel: string; line: number; snippet: string }[]>`
|
|
55
|
-
- **Параметри:**
|
|
56
|
-
- `absPackageRoot` — абсолютний шлях до кореня пакета.
|
|
57
|
-
- `files` — перелік відносних шляхів-кандидатів, відфільтрованих через `isEsbuildScanFile`.
|
|
58
|
-
- `maxMatches` — максимальна кількість збігів, які треба зібрати.
|
|
59
|
-
- **Повертає:** `Promise` зі списком знайдених збігів `{ rel, line, snippet }`.
|
|
60
|
-
- **Логіка:** для кожного файлу читає вміст через `fs/promises.readFile(..., 'utf8')`; якщо у файлі немає згадки `esbuild`, переходить далі. Інакше викликає `appendEsbuildLineMatches`. Зупиняється, щойно `matches.length` досягає `maxMatches`.
|
|
61
|
-
- **Side effects:** виконує читання файлів з диска.
|
|
62
|
-
|
|
63
|
-
### `checkEsbuildMentions(rootDir, absPackageRoot, ignorePaths, prefix, passFn, fail)`
|
|
64
|
-
|
|
65
|
-
- **Сигнатура:** `async function checkEsbuildMentions(rootDir: string, absPackageRoot: string, ignorePaths: string[], prefix: string, passFn: (msg: string) => void, fail: (msg: string) => void): Promise<void>`
|
|
66
|
-
- **Параметри:**
|
|
67
|
-
- `rootDir` — відносний шлях до пакета (для повідомлень).
|
|
68
|
-
- `absPackageRoot` — абсолютний шлях до кореня пакета (для обходу).
|
|
69
|
-
- `ignorePaths` — масив абсолютних шляхів каталогів, які повністю виключені з обходу.
|
|
70
|
-
- `prefix` — текстовий префікс для повідомлень (`[<label>] `).
|
|
71
|
-
- `passFn` — callback на успішне повідомлення (як у check-reporter).
|
|
72
|
-
- `fail` — callback на помилку перевірки.
|
|
73
|
-
- **Повертає:** `Promise<void>`.
|
|
74
|
-
- **Логіка:** обходить дерево через `walkDir(absPackageRoot, visitor, ignorePaths)`; кожен файл прогоняється через `isEsbuildScanFile`; кандидати збираються у локальний масив. Далі викликає `collectEsbuildMatchesInFiles` з лімітом `maxMatches = 30`. Якщо збігів немає — друкує pass із підказкою «очікується `rolldown`». Якщо є — реєструє `fail` на кожен збіг з підказкою замінити на `rolldown` та (якщо ліміт вичерпано) додає ще один `fail`, що показано лише перші 30.
|
|
75
|
-
- **Side effects:** виконує читання файлів з диска; викликає `passFn`/`fail`.
|
|
76
|
-
|
|
77
|
-
### `packageLabel(rootDir)`
|
|
78
|
-
|
|
79
|
-
- **Сигнатура:** `function packageLabel(rootDir: string): string`
|
|
80
|
-
- **Параметри:**
|
|
81
|
-
- `rootDir` — відносний шлях до пакета (`'.'` для кореня monorepo або, наприклад, `site`).
|
|
82
|
-
- **Повертає:** `string` — підпис для логів: `'корінь'` якщо `rootDir === '.'`, інакше сам `rootDir`.
|
|
83
|
-
- **Side effects:** немає.
|
|
84
|
-
|
|
85
|
-
### `ukFilesCountPhrase(n)`
|
|
86
|
-
|
|
87
|
-
- **Сигнатура:** `function ukFilesCountPhrase(n: number): string`
|
|
88
|
-
- **Параметри:**
|
|
89
|
-
- `n` — невід’ємна кількість файлів.
|
|
90
|
-
- **Повертає:** фразу українською мовою з відмінком «файл» / «файли» / «файлів» відповідно до правил pluralization:
|
|
91
|
-
- залишок від 100 у діапазоні 11..14 → `«N файлів»`;
|
|
92
|
-
- залишок від 10 рівний 1 → `«N файл»`;
|
|
93
|
-
- залишок від 10 у 2..4 → `«N файли»`;
|
|
94
|
-
- решта → `«N файлів»`.
|
|
95
|
-
- **Side effects:** немає.
|
|
96
|
-
|
|
97
|
-
### `checkViteClientEnvAndEditorConfig(rootDir, prefix, passFn, fail, cwd)`
|
|
98
|
-
|
|
99
|
-
- **Сигнатура:** `async function checkViteClientEnvAndEditorConfig(rootDir: string, prefix: string, passFn: (msg: string) => void, fail: (msg: string) => void, cwd: string): Promise<void>`
|
|
100
|
-
- **Параметри:**
|
|
101
|
-
- `rootDir` — відносний шлях до кореня пакета.
|
|
102
|
-
- `prefix` — префікс повідомлень.
|
|
103
|
-
- `passFn` / `fail` — callbacks check-reporter-а.
|
|
104
|
-
- `cwd` — корінь репозиторію.
|
|
105
|
-
- **Повертає:** `Promise<void>`.
|
|
106
|
-
- **Логіка:**
|
|
107
|
-
1. Перевіряє, що `<cwd>/<rootDir>/src/vite-env.d.ts` існує; якщо ні — `fail` з підказкою про `/// <reference types="vite/client" />`.
|
|
108
|
-
2. Якщо файл існує, читає його вміст і перевіряє регулярним виразом `VITE_CLIENT_REFERENCE_RE = /\/\/\/\s*<reference\s+types\s*=\s*["']vite\/client["']\s*\/>/`. За відсутності збігу — `fail`.
|
|
109
|
-
3. Якщо обидва кроки успішні — `passFn` про коректний `vite-env.d.ts`.
|
|
110
|
-
4. Перевіряє наявність `<cwd>/<rootDir>/jsconfig.json`; за відсутності — `fail`, інакше `passFn`.
|
|
111
|
-
- **Side effects:** читання файлів з диска; виклики `passFn`/`fail`.
|
|
112
|
-
|
|
113
|
-
### `isVueComponentLibraryPkg(pkg)` _(експорт)_
|
|
114
|
-
|
|
115
|
-
- **Сигнатура:** `function isVueComponentLibraryPkg(pkg: { peerDependencies?: Record<string, string> }): boolean`
|
|
116
|
-
- **Параметри:**
|
|
117
|
-
- `pkg` — розпарсений `package.json` пакета.
|
|
118
|
-
- **Повертає:** `boolean` — `true`, якщо `vue` присутній у `peerDependencies`.
|
|
119
|
-
- **Семантика:** такі пакети — бібліотеки компонентів Vue. Їхні джерела не проходять через `unplugin-auto-import` споживача (auto-import резолвиться лише в коді додатка, не в `node_modules`), тому правило «без явних value-імпортів з `'vue'`» до них не застосовується.
|
|
120
|
-
- **Side effects:** немає.
|
|
121
|
-
|
|
122
|
-
### `extractAutoImportCallArgs(content)`
|
|
123
|
-
|
|
124
|
-
- **Сигнатура:** `function extractAutoImportCallArgs(content: string): string | null`
|
|
125
|
-
- **Параметри:**
|
|
126
|
-
- `content` — повний текст `vite.config.*`.
|
|
127
|
-
- **Повертає:** текст усередині найближчого виклику `AutoImport(...)` без зовнішніх дужок, або `null`, якщо виклик не знайдено або дужки не збалансовані.
|
|
128
|
-
- **Логіка:** шукає marker `AutoImport(`, після нього просувається посимвольно з лічильником глибини дужок (`(` → `+1`, `)` → `-1`) і повертає підрядок від першого символу після `(` до символу, на якому `depth` стає `0`.
|
|
129
|
-
- **Side effects:** немає.
|
|
130
|
-
|
|
131
|
-
### `viteConfigHasVueInAutoImports(content)`
|
|
132
|
-
|
|
133
|
-
- **Сигнатура:** `function viteConfigHasVueInAutoImports(content: string): boolean`
|
|
134
|
-
- **Параметри:**
|
|
135
|
-
- `content` — повний текст `vite.config.*`.
|
|
136
|
-
- **Повертає:** `boolean` — `true`, якщо у `AutoImport(...)` як рядковий елемент `imports` фігурує `'vue'` або `"vue"`.
|
|
137
|
-
- **Логіка:** делегує до `extractAutoImportCallArgs`; якщо `null` — `false`; інакше повертає `args.includes("'vue'") || args.includes('"vue"')`. Зауважте: перевірка є текстовим contains, без парсингу JS — точкою обʼєктивізації пошуку є вже відокремлений виклик `AutoImport(...)`.
|
|
138
|
-
- **Side effects:** немає.
|
|
139
|
-
|
|
140
|
-
### `checkViteConfig(rootDir, isComponentLibrary, prefix, passFn, fail, cwd)`
|
|
141
|
-
|
|
142
|
-
- **Сигнатура:** `async function checkViteConfig(rootDir: string, isComponentLibrary: boolean, prefix: string, passFn: (msg: string) => void, fail: (msg: string) => void, cwd: string): Promise<{ hasVueAutoImport: boolean }>`
|
|
143
|
-
- **Параметри:**
|
|
144
|
-
- `rootDir` — відносний шлях до пакета.
|
|
145
|
-
- `isComponentLibrary` — чи це бібліотека компонентів Vue.
|
|
146
|
-
- `prefix`, `passFn`, `fail` — як вище.
|
|
147
|
-
- `cwd` — корінь репозиторію.
|
|
148
|
-
- **Повертає:** `Promise<{ hasVueAutoImport: boolean }>` — ознака, чи AutoImport сконфігуровано на `'vue'`. Її використовує `checkVueImportViolations`.
|
|
149
|
-
- **Логіка:**
|
|
150
|
-
1. Шукає перший наявний з `vite.config.js`, `vite.config.ts`, `vite.config.mjs`; якщо жоден не існує — `fail` і повертає `{ hasVueAutoImport: false }`.
|
|
151
|
-
2. Читає вміст vite.config.
|
|
152
|
-
3. Якщо вміст містить `esbuild` (за регуляркою `ESBUILD_RE`) — `fail` з підказкою замінити на `rolldown`.
|
|
153
|
-
4. Викликає `viteConfigHasVueInAutoImports(content)` → `hasVueAutoImport`.
|
|
154
|
-
5. Якщо це бібліотека компонентів — `passFn`, що `VueMacros`/`AutoImport` не вимагаються.
|
|
155
|
-
6. Інакше — пробігає список перевірок `[ VueMacros, AutoImport ]` і реєструє `passFn`/`fail` за наявністю токенів у вмісті. Якщо у файлі є виклик `AutoImport(`, додатково перевіряє `hasVueAutoImport`: `pass` — якщо `'vue'` у `imports`, інакше `fail` з підказкою додати `'vue'` (бо інакше прибирати явні value-імпорти `from 'vue'` небезпечно).
|
|
156
|
-
7. Незалежно від типу пакета, якщо у vite.config фігурує `process.env.npm_lifecycle_event` — `fail` з підказкою перейти на `mode` з `defineConfig(({ mode }) => ...)` (Bun не підставляє `npm_lifecycle_event` так, як npm).
|
|
157
|
-
- **Side effects:** читання `vite.config.*` з диска; виклики `passFn`/`fail`.
|
|
158
|
-
|
|
159
|
-
### `checkVueNodeImportViolations(rootDir, absPackageRoot, ignorePaths, prefix, passFn, fail)`
|
|
160
|
-
|
|
161
|
-
- **Сигнатура:** `async function checkVueNodeImportViolations(rootDir: string, absPackageRoot: string, ignorePaths: string[], prefix: string, passFn: (msg: string) => void, fail: (msg: string) => void): Promise<void>`
|
|
162
|
-
- **Параметри:** як в інших чек-функцій; `absPackageRoot` — абсолютний шлях до пакета.
|
|
163
|
-
- **Повертає:** `Promise<void>`.
|
|
164
|
-
- **Логіка:**
|
|
165
|
-
1. Обходить `absPackageRoot` через `walkDir(absPackageRoot, visitor, ignorePaths)`, збирає абсолютні шляхи всіх `.vue`-файлів, що не пропускаються через `shouldSkipFileForVueImportScan(rel)`.
|
|
166
|
-
2. Для кожного `.vue` читає вміст і викликає `findForbiddenNodeImportsInVueFile(content, rel)`; на кожне порушення — `fail` з підказкою винести логіку у server-side утіліту (SFC виконується у браузері, Node API недоступне).
|
|
167
|
-
3. Якщо порушень немає — `passFn` з фразою «`немає імпортів Node-нативних модулів у .vue (проскановано N файлів)`», де `N` форматується через `ukFilesCountPhrase`.
|
|
168
|
-
- **Side effects:** обхід та читання файлів з диска; виклики `passFn`/`fail`.
|
|
169
|
-
|
|
170
|
-
### `checkVueImportViolations(rootDir, absPackageRoot, ignorePaths, isComponentLibrary, hasVueAutoImport, prefix, passFn, fail)`
|
|
171
|
-
|
|
172
|
-
- **Сигнатура:** `async function checkVueImportViolations(rootDir: string, absPackageRoot: string, ignorePaths: string[], isComponentLibrary: boolean, hasVueAutoImport: boolean, prefix: string, passFn: (msg: string) => void, fail: (msg: string) => void): Promise<void>`
|
|
173
|
-
- **Параметри:**
|
|
174
|
-
- `rootDir` — відносний шлях до пакета.
|
|
175
|
-
- `absPackageRoot` — абсолютний шлях до кореня пакета.
|
|
176
|
-
- `ignorePaths` — каталоги, повністю виключені з обходу.
|
|
177
|
-
- `isComponentLibrary` — чи це бібліотека компонентів (`vue` у `peerDependencies`).
|
|
178
|
-
- `hasVueAutoImport` — чи AutoImport сконфігуровано на `'vue'` (з `checkViteConfig`).
|
|
179
|
-
- `prefix`, `passFn`, `fail` — як вище.
|
|
180
|
-
- **Повертає:** `Promise<void>`.
|
|
181
|
-
- **Логіка:**
|
|
182
|
-
1. Якщо `isComponentLibrary === true` — `passFn` із поясненням, що для бібліотек компонентів явні value-імпорти з `'vue'` дозволені, і повертається. Джерела бібліотеки не проходять через `unplugin-auto-import` споживача.
|
|
183
|
-
2. Інакше якщо `hasVueAutoImport === false` — `passFn` з підказкою спершу додати `'vue'` до `AutoImport.imports` (fail про це вже зареєстровано в `checkViteConfig`), і повертається.
|
|
184
|
-
3. Інакше обходить пакет через `walkDir`, збирає абсолютні шляхи всіх source-файлів, для яких `isVueImportScanSourceFile(rel) === true` і `shouldSkipFileForVueImportScan(rel) === false`.
|
|
185
|
-
4. Для кожного такого файлу читає вміст і викликає `findForbiddenVueImportsInSourceFile(content, rel)`; на кожне порушення — `fail` з підказкою прибрати явний value-імпорт з `'vue'`.
|
|
186
|
-
5. Якщо порушень не знайдено — `passFn` з фразою «немає заборонених value-імпортів з `'vue'` у джерелах (проскановано N файлів)».
|
|
187
|
-
- **Side effects:** обхід та читання файлів з диска; виклики `passFn`/`fail`.
|
|
188
|
-
|
|
189
|
-
### `checkVuePackage(rootDir, isComponentLibrary, ignorePaths, fail, passFn, cwd)`
|
|
190
|
-
|
|
191
|
-
- **Сигнатура:** `async function checkVuePackage(rootDir: string, isComponentLibrary: boolean, ignorePaths: string[], fail: (msg: string) => void, passFn: (msg: string) => void, cwd: string): Promise<void>`
|
|
192
|
-
- **Параметри:**
|
|
193
|
-
- `rootDir` — відносний шлях до пакета.
|
|
194
|
-
- `isComponentLibrary` — чи це бібліотека компонентів Vue.
|
|
195
|
-
- `ignorePaths` — каталоги, повністю виключені з обходу.
|
|
196
|
-
- `fail`, `passFn` — callbacks check-reporter-а (порядок `fail` перед `passFn` тут зворотний до інших функцій).
|
|
197
|
-
- `cwd` — корінь репозиторію.
|
|
198
|
-
- **Повертає:** `Promise<void>` — завершується після усього набору перевірок пакета.
|
|
199
|
-
- **Логіка послідовно виконує:**
|
|
200
|
-
1. Формує `prefix = "[" + packageLabel(rootDir) + "] "`.
|
|
201
|
-
2. Реєструє інформаційний `passFn`: «`package.json` залежності перевіряє `npx @nitra/cursor fix → vue.package_json`».
|
|
202
|
-
3. `checkViteClientEnvAndEditorConfig(rootDir, prefix, passFn, fail, cwd)`.
|
|
203
|
-
4. `checkViteConfig(rootDir, isComponentLibrary, prefix, passFn, fail, cwd)` → отримує `hasVueAutoImport`.
|
|
204
|
-
5. `checkVueImportViolations(rootDir, join(cwd, rootDir), ignorePaths, isComponentLibrary, hasVueAutoImport, prefix, passFn, fail)`.
|
|
205
|
-
6. `checkVueNodeImportViolations(rootDir, join(cwd, rootDir), ignorePaths, prefix, passFn, fail)`.
|
|
206
|
-
7. `checkEsbuildMentions(rootDir, join(cwd, rootDir), ignorePaths, prefix, passFn, fail)`.
|
|
207
|
-
- **Side effects:** виконує всі вкладені перевірки (читання файлів, виклики `passFn`/`fail`).
|
|
208
|
-
|
|
209
|
-
### `collectVueRoots(roots, cwd)`
|
|
210
|
-
|
|
211
|
-
- **Сигнатура:** `async function collectVueRoots(roots: string[], cwd: string): Promise<Array<{ rootDir: string, isComponentLibrary: boolean }>>`
|
|
212
|
-
- **Параметри:**
|
|
213
|
-
- `roots` — усі корені пакетів monorepo (відносні шляхи), отримані від `getMonorepoPackageRootDirs`.
|
|
214
|
-
- `cwd` — корінь репозиторію.
|
|
215
|
-
- **Повертає:** масив описів пакетів, у яких `vue` зазначений у `dependencies`, з ознакою `isComponentLibrary`.
|
|
216
|
-
- **Логіка:**
|
|
217
|
-
1. Для кожного `r` будує абсолютний шлях `<cwd>/<r>/package.json` і пропускає його, якщо файл відсутній.
|
|
218
|
-
2. Парсить JSON-вміст `package.json`.
|
|
219
|
-
3. Якщо `pkg.dependencies?.vue` істина — додає до результату об’єкт `{ rootDir: r, isComponentLibrary: isVueComponentLibraryPkg(pkg) }`.
|
|
220
|
-
4. Пакети, у яких `vue` лише в `peerDependencies` (без `dependencies`), не додаються — це самостійні бібліотеки компонентів, до них app-перевірки не застосовуються.
|
|
221
|
-
- **Side effects:** читання `package.json` файлів з диска.
|
|
222
|
-
|
|
223
|
-
### `checkVueVolarRecommendation(pass, fail, cwd)`
|
|
224
|
-
|
|
225
|
-
- **Сигнатура:** `async function checkVueVolarRecommendation(pass: (msg: string) => void, fail: (msg: string) => void, cwd: string): Promise<void>`
|
|
226
|
-
- **Параметри:**
|
|
227
|
-
- `pass`, `fail` — callbacks check-reporter-а.
|
|
228
|
-
- `cwd` — корінь репозиторію.
|
|
229
|
-
- **Повертає:** `Promise<void>`.
|
|
230
|
-
- **Логіка:**
|
|
231
|
-
1. Перевіряє наявність `<cwd>/.vscode/extensions.json`; за відсутності — `fail` з поясненням, що для Vue-проєкту потрібна рекомендація `Vue.volar`.
|
|
232
|
-
2. Парсить JSON; якщо `recommendations` містить `'Vue.volar'` — `pass`, інакше — `fail` з підказкою додати рекомендацію.
|
|
233
|
-
- **Side effects:** читання `extensions.json` з диска; виклики `pass`/`fail`.
|
|
234
|
-
|
|
235
|
-
### `check(cwd)` _(експорт, точка входу)_
|
|
236
|
-
|
|
237
|
-
- **Сигнатура:** `async function check(cwd: string = process.cwd()): Promise<number>`
|
|
238
|
-
- **Параметри:**
|
|
239
|
-
- `cwd` — корінь репозиторію; за замовчуванням `process.cwd()`.
|
|
240
|
-
- **Повертає:** `Promise<number>` — `0`, якщо всі перевірки успішні; `1`, якщо є зареєстровані `fail`.
|
|
241
|
-
- **Логіка:**
|
|
242
|
-
1. Створює `reporter = createCheckReporter()` і деструктурує `{ pass, fail }`.
|
|
243
|
-
2. Отримує корені всіх workspace-пакетів через `getMonorepoPackageRootDirs(cwd)`.
|
|
244
|
-
3. Викликає `collectVueRoots(roots, cwd)` → список Vue-пакетів.
|
|
245
|
-
4. Якщо список порожній — друкує два `pass`-повідомлення (про пропуск Volar і про відсутність `vue` у будь-яких `dependencies`) і одразу повертає `reporter.getExitCode()`.
|
|
246
|
-
5. Інакше викликає `checkVueVolarRecommendation(pass, fail, cwd)`.
|
|
247
|
-
6. Завантажує абсолютні `ignorePaths` через `loadCursorIgnorePaths(cwd)` (читає `.cursorignore`-подібну конфігурацію).
|
|
248
|
-
7. Для кожного `{ rootDir, isComponentLibrary }` із `vueRoots` викликає `checkVuePackage(rootDir, isComponentLibrary, ignorePaths, fail, pass, cwd)`.
|
|
249
|
-
8. Повертає `reporter.getExitCode()`.
|
|
250
|
-
- **Side effects:** усе разом — повний обхід monorepo, читання багатьох файлів з диска, накопичення pass/fail у check-reporter-і.
|
|
251
|
-
|
|
252
|
-
## Залежності
|
|
253
|
-
|
|
254
|
-
### Імпорти зі стандартної бібліотеки Node.js
|
|
255
|
-
|
|
256
|
-
- `node:fs` — `existsSync` (синхронна перевірка існування файлу).
|
|
257
|
-
- `node:fs/promises` — `readFile` (асинхронне читання файлу як `utf8`).
|
|
258
|
-
- `node:path` — `join`, `relative` (компонування і обчислення відносних шляхів).
|
|
259
|
-
|
|
260
|
-
### Внутрішні модулі проєкту
|
|
261
|
-
|
|
262
|
-
- `../../../scripts/lib/check-reporter.mjs` — `createCheckReporter()`: створює reporter з API `{ pass, fail, getExitCode }`, який накопичує повідомлення перевірки та підраховує підсумковий exit-код.
|
|
263
|
-
- `../lib/vue-forbidden-imports.mjs` — функції сканування заборонених імпортів:
|
|
264
|
-
- `findForbiddenNodeImportsInVueFile(content, rel)` — повертає список порушень із Node-імпортами у `.vue` SFC.
|
|
265
|
-
- `findForbiddenVueImportsInSourceFile(content, rel)` — повертає список явних value-імпортів з `'vue'` у звичайних source-файлах.
|
|
266
|
-
- `isVueImportScanSourceFile(rel)` — чи варто файл взагалі сканувати на value-імпорти з `'vue'` (за розширенням/типом).
|
|
267
|
-
- `shouldSkipFileForVueImportScan(rel)` — predicate-фільтр (`node_modules/`, `dist/`, lock-файли тощо).
|
|
268
|
-
- `../../../scripts/lib/load-cursor-config.mjs` — `loadCursorIgnorePaths(cwd)`: повертає масив абсолютних шляхів каталогів, які повністю виключаються з обходу.
|
|
269
|
-
- `../../../scripts/utils/walkDir.mjs` — `walkDir(absRoot, visitor, ignorePaths)`: рекурсивний обхід дерева; visitor викликається з абсолютним шляхом кожного файлу.
|
|
270
|
-
- `../../../scripts/lib/workspaces.mjs` — `getMonorepoPackageRootDirs(cwd)`: повертає відносні шляхи всіх workspace-пакетів monorepo (включно з коренем `'.'`, якщо він є пакетом).
|
|
271
|
-
|
|
272
|
-
### Зовнішні (вказані у документації, не у коді цього модуля)
|
|
273
|
-
|
|
274
|
-
- `oxc-parser` — використовується транзитивно через `../lib/vue-forbidden-imports.mjs` для парсингу і аналізу `module.staticImports`. У самому `packages.mjs` прямого виклику парсера немає.
|
|
275
|
-
- Vue/Vite-стек, для якого писано перевірки: `vite >= 8`, `@vitejs/plugin-vue`, `vue-macros`, `unplugin-auto-import`, `vite-plugin-vue-layouts-next`. Заборонено: `esbuild` (треба використовувати `rolldown`).
|
|
276
|
-
|
|
277
|
-
### Константи
|
|
278
|
-
|
|
279
|
-
- `ESBUILD_RE = /\besbuild\b/` — регулярний вираз для пошуку слова `esbuild` як цілого ідентифікатора.
|
|
280
|
-
- `VITE_CLIENT_REFERENCE_RE = /\/\/\/\s*<reference\s+types\s*=\s*["']vite\/client["']\s*\/>/` — triple-slash-директива для `vite/client` у `src/vite-env.d.ts`.
|
|
281
|
-
|
|
282
|
-
## Потік виконання / Використання
|
|
283
|
-
|
|
284
|
-
### Виклик
|
|
285
|
-
|
|
286
|
-
Модуль експортує `check(cwd)`. Зовнішній runner (CLI `@nitra/cursor` або pipeline-перевірка) викликає його приблизно так:
|
|
287
|
-
|
|
288
|
-
```js
|
|
289
|
-
import { check } from './npm/rules/vue/js/packages.mjs'
|
|
290
|
-
|
|
291
|
-
const code = await check(process.cwd())
|
|
292
|
-
process.exit(code)
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
### Послідовність кроків `check()`
|
|
12
|
+
isVueComponentLibraryPkg
|
|
13
|
+
Перевіряє, чи є пакет бібліотекою компонентів Vue шляхом перевірки `peerDependencies`.
|
|
296
14
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
3. Фільтрація пакетів через `collectVueRoots(roots, cwd)`: залишаються лише ті, що мають `vue` у `dependencies`. Кожному обчислюється `isComponentLibrary` через `isVueComponentLibraryPkg(pkg)` (за наявністю `vue` у `peerDependencies`).
|
|
300
|
-
4. Якщо Vue-пакетів немає — друкує два інформаційних `pass`-повідомлення і повертає exit-код reporter-а (`0`).
|
|
301
|
-
5. Перевіряє `.vscode/extensions.json` на рекомендацію `Vue.volar` (`checkVueVolarRecommendation`).
|
|
302
|
-
6. Завантажує `ignorePaths` через `loadCursorIgnorePaths(cwd)`.
|
|
303
|
-
7. Для кожного Vue-пакета послідовно виконує `checkVuePackage`:
|
|
304
|
-
1. Інформаційний `pass` про `package.json`-перевірку через `npx @nitra/cursor fix → vue.package_json`.
|
|
305
|
-
2. `checkViteClientEnvAndEditorConfig` — `src/vite-env.d.ts` + `jsconfig.json`.
|
|
306
|
-
3. `checkViteConfig` — наявність `vite.config.*`, `VueMacros`, `AutoImport`, `'vue'` у `AutoImport.imports`, заборона `process.env.npm_lifecycle_event`, заборона `esbuild` у vite.config.
|
|
307
|
-
4. `checkVueImportViolations` — скан source-файлів пакета на заборонені value-імпорти з `'vue'` (тільки якщо це не бібліотека компонентів і AutoImport налаштовано на `'vue'`).
|
|
308
|
-
5. `checkVueNodeImportViolations` — скан `.vue` SFC на заборонені імпорти Node-нативних модулів.
|
|
309
|
-
6. `checkEsbuildMentions` — текстовий скан усіх scan-сумісних файлів пакета на згадки `esbuild` із підказкою переходу на `rolldown`.
|
|
310
|
-
8. Повертає `reporter.getExitCode()` — `0` за умови відсутності `fail`, `1` за наявності.
|
|
15
|
+
check
|
|
16
|
+
Перевіряє залежності та конфігурацію vite.config одного Vue-пакета.
|
|
311
17
|
|
|
312
|
-
|
|
18
|
+
## Поведінка
|
|
313
19
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
- Скан value-імпортів `'vue'` пропускається, якщо `'vue'` ще не доданий до `AutoImport.imports` — інакше пропозиція прибрати імпорти зламала б код (нікому буде надати `ref`/`createApp` тощо). Користувача спершу штовхають полагодити `vite.config`, і лише наступний прогін викриє самі заборонені імпорти.
|
|
317
|
-
- Бібліотеки компонентів (`vue` у `peerDependencies`) звільнюються від вимог `VueMacros`/`AutoImport` і правила «без явних value-імпортів з `'vue'`».
|
|
318
|
-
- Сканування `.vue` SFC на Node-імпорти виконується завжди, незалежно від типу пакета.
|
|
319
|
-
- Скан `esbuild`-згадок має жорсткий ліміт у 30 збігів; при перевищенні додатково реєструється fail-маркер «показано перші 30 збігів».
|
|
320
|
-
- Обхід `walkDir` керується `ignorePaths` із `.cursor`-конфігу; усередині кожної чек-функції додатково діють фільтри `isEsbuildScanFile` / `isVueImportScanSourceFile` / `shouldSkipFileForVueImportScan`.
|
|
20
|
+
isVueComponentLibraryPkg
|
|
21
|
+
Визначає, чи є пакет бібліотекою компонентів Vue через peerDependencies
|
|
321
22
|
|
|
322
|
-
|
|
23
|
+
check
|
|
24
|
+
Перевіряє залежності та vite.config одного Vue-пакета
|
|
323
25
|
|
|
324
|
-
|
|
325
|
-
- `check(cwd)` — основна публічна точка для запуску перевірки. Повертає exit-код, який інтегрується у будь-який runner перевірок.
|
|
26
|
+
## Публічний API
|
|
326
27
|
|
|
327
|
-
|
|
28
|
+
isVueComponentLibraryPkg — забезпечує, що `+` використовується для підхоплення `vite-env.d.ts` та `.vue`.
|
|
29
|
+
passFn — перевіряє наявність `prefixjsconfig.json`.
|
|
30
|
+
check — перевіряє, чи є `vue` у `peerDependencies` пакету бібліотеки. Якщо `vue` є залежністю, то правило авто-імпорту (заборона value-імпортів з `'vue'`) не застосовується до цієї бібліотеки, оскільки імпорти з `'vue'` повинні бути явними.
|
|
328
31
|
|
|
329
|
-
|
|
32
|
+
## Гарантії поведінки
|
|
330
33
|
|
|
331
|
-
-
|
|
332
|
-
-
|
|
333
|
-
-
|
|
334
|
-
-
|
|
335
|
-
- Зафіксовано інваріанти: ліміт у 30 esbuild-збігів, виключення для бібліотек компонентів, пропуск value-імпорт-скану до додавання `'vue'` у `AutoImport.imports`, скан Node-імпортів у `.vue` незалежно від типу пакета, заборона `process.env.npm_lifecycle_event` у vite.config (Bun-сумісність), вимога `mode` з `defineConfig(({ mode }) => ...)`.
|
|
34
|
+
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
35
|
+
- За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
|
|
36
|
+
- Свідомо пропускає шляхи: `.git`, `node_modules`.
|
|
37
|
+
- Не звертається до мережі.
|
|
@@ -1,161 +1,42 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
docgen:
|
|
3
|
+
source: npm/rules/worktree/fix.mjs
|
|
4
|
+
crc: 38cf876b
|
|
5
|
+
score: 100
|
|
6
|
+
---
|
|
2
7
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Файл `npm/rules/worktree/fix.mjs` — це **точка входу правила `worktree`** для пакета `@nitra/cursor`. Він реалізує **дві ролі одночасно** (dual role):
|
|
6
|
-
|
|
7
|
-
1. **Library mode** — експортує функцію `run(ctx)`, яку CLI-оркестратор `@nitra/cursor` (або інший runner) викликає через `import { run } from '.../fix.mjs'` для запуску правила в межах батч-прогону всіх правил.
|
|
8
|
-
2. **Standalone mode** — якщо файл запускається напряму через `bun npm/rules/worktree/fix.mjs`, він самостійно ініціалізує CLI-обгортку (config-loading, whitelist, summary) і завершує процес `exit-code`-ом, придатним для CI/IDE.
|
|
9
|
-
|
|
10
|
-
Сам файл **не містить власної логіки перевірки** — він лише делегує виконання стандартному раннеру `runStandardRule`, який послідовно виконує підкроки правила в наступному порядку:
|
|
11
|
-
|
|
12
|
-
- **applies** — детектор, чи застосовне правило до конкретного файлу/директорії;
|
|
13
|
-
- **JS-concerns** — JS-перевірки (зокрема `check-*.mjs` у директорії правила);
|
|
14
|
-
- **policy** — політики/декларативні перевірки;
|
|
15
|
-
- **mdc-refs** — перевірка посилань у відповідному `.mdc`-документі правила.
|
|
16
|
-
|
|
17
|
-
Каталог `worktree/` стосується доменного правила про **git worktree** (див. `.cursor/rules/n-worktree.mdc`) — конвенцій ізольованих робочих дерев у `.worktrees/<branch>/` та інвентарних описів. Сам `fix.mjs` не реалізує цих перевірок безпосередньо — він лише диспетчеризує їх через стандартний пайплайн.
|
|
18
|
-
|
|
19
|
-
## Експорти / API
|
|
20
|
-
|
|
21
|
-
| Експорт | Тип | Призначення |
|
|
22
|
-
| ------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
23
|
-
| `run` | `function (ctx?: RuleContext): Promise<number>` | Library-entry. Запускає стандартний пайплайн правила для директорії, в якій знаходиться `fix.mjs`. Повертає **exit-code**: `0` — порушень немає, `1` — є порушення. |
|
|
24
|
-
|
|
25
|
-
Файл також містить **side-effect блок** (виконується тільки при прямому запуску як CLI), який не є експортом, але є частиною контракту:
|
|
26
|
-
|
|
27
|
-
- При `isRunAsCli(import.meta.url) === true` модуль викликає `runRuleCli(import.meta.dirname)` і завершує процес `process.exit(<code>)`.
|
|
28
|
-
|
|
29
|
-
## Функції
|
|
30
|
-
|
|
31
|
-
### `run(ctx)`
|
|
32
|
-
|
|
33
|
-
**Сигнатура:**
|
|
34
|
-
|
|
35
|
-
```js
|
|
36
|
-
export function run(ctx)
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
**Параметри:**
|
|
40
|
-
|
|
41
|
-
| Параметр | Тип | Обов'язковий | Опис |
|
|
42
|
-
| -------- | ----------------------------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
43
|
-
| `ctx` | `RuleContext` (з `../../scripts/lib/run-standard-rule.mjs`) | Ні | Контекст прогону правила. Передається оркестратором із `@nitra/cursor` і містить, зокрема, спільні структури на кшталт `walkCache` (кеш обходу файлової системи між кількома правилами в одному прогоні). Якщо не передано — раннер створить дефолтний контекст. |
|
|
44
|
-
|
|
45
|
-
**Повертає:** `Promise<number>` — exit-code:
|
|
46
|
-
|
|
47
|
-
- `0` — правило виконалося без порушень;
|
|
48
|
-
- `1` — знайдено порушення (інтерпретація залежить від `runStandardRule`).
|
|
49
|
-
|
|
50
|
-
**Side effects:**
|
|
51
|
-
|
|
52
|
-
- Сама `run` не пише в `stdout` напряму та не змінює FS — усі побічні ефекти інкапсульовані в `runStandardRule` (форматований вивід summary, потенційне читання `.mdc`/`check-*.mjs`-файлів сусідньої директорії, обхід проєктних файлів через `walkCache`).
|
|
53
|
-
- `run` **не** викликає `process.exit` — це відповідальність standalone-блоку нижче.
|
|
54
|
-
|
|
55
|
-
**Поведінкова ідіома:**
|
|
56
|
-
|
|
57
|
-
`run` — це тонкий **прокладочний шар**: він фіксує **директорію** правила (`import.meta.dirname`), бо саме за нею раннер визначає `id` правила (ім'я каталогу `worktree`), знаходить сусідні файли (`policy.mjs`, `applies.mjs`, `check-*.mjs`, `<id>.mdc`) та збирає пайплайн.
|
|
8
|
+
# fix.mjs
|
|
58
9
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
Анонімний side-effect блок, що виконується лише при прямому запуску:
|
|
62
|
-
|
|
63
|
-
```js
|
|
64
|
-
if (isRunAsCli(import.meta.url)) {
|
|
65
|
-
process.exit(await runRuleCli(import.meta.dirname))
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
**Поведінка:**
|
|
70
|
-
|
|
71
|
-
- `isRunAsCli(import.meta.url)` повертає `true`, якщо модуль є **головним** entry-point процесу (а не імпортований). Це типова заміна паттерну `require.main === module` для ESM.
|
|
72
|
-
- `runRuleCli(import.meta.dirname)` — повна CLI-обгортка над `run`: завантажує проєктний config, застосовує whitelist (наприклад, виключення з `.cursorignore`/конфігу), друкує summary після виконання та повертає підсумковий exit-code.
|
|
73
|
-
- `process.exit(code)` — закриває процес з кодом, придатним для CI/IDE. Лінт-винятки `n/no-process-exit` та `unicorn/no-process-exit` свідомо вимкнені коментарем, бо standalone entry-point має лагідно виходити з конкретним кодом, інакше CI не отримає сигналу про fail.
|
|
74
|
-
|
|
75
|
-
## Залежності
|
|
76
|
-
|
|
77
|
-
Внутрішні залежності (відносні до `npm/scripts/lib/`):
|
|
78
|
-
|
|
79
|
-
| Імпорт | З файлу | Призначення |
|
|
80
|
-
| ----------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
81
|
-
| `isRunAsCli` | `../../scripts/lib/run-rule-cli.mjs` | Перевіряє, чи поточний модуль є головним процесом (заміна `require.main === module` для ESM). |
|
|
82
|
-
| `runRuleCli` | `../../scripts/lib/run-rule-cli.mjs` | Standalone-обгортка: config-loading + whitelist + summary + exit-code. Еквівалент `npx @nitra/cursor fix <id>` для одного правила. |
|
|
83
|
-
| `runStandardRule` | `../../scripts/lib/run-standard-rule.mjs` | Стандартний пайплайн правила: applies → JS-concerns → policy → mdc-refs. Приймає директорію правила та опційний `RuleContext`. |
|
|
84
|
-
|
|
85
|
-
Зовнішні залежності та глобальні API:
|
|
86
|
-
|
|
87
|
-
- `import.meta.dirname` — ESM-аналог `__dirname`; використовується для передачі шляху до каталогу правила раннерам.
|
|
88
|
-
- `import.meta.url` — використовується `isRunAsCli` для визначення головного модуля.
|
|
89
|
-
- `process.exit(code)` — Node.js/Bun runtime API для встановлення exit-code.
|
|
90
|
-
|
|
91
|
-
Файл **не залежить** напряму від конкретних `check-*.mjs`, `policy.mjs`, `<id>.mdc` сусідньої директорії — їх відкриває та інтерпретує `runStandardRule`.
|
|
92
|
-
|
|
93
|
-
## Потік виконання / Використання
|
|
94
|
-
|
|
95
|
-
### Сценарій A — Library mode (виклик з оркестратора)
|
|
96
|
-
|
|
97
|
-
```js
|
|
98
|
-
import { run } from '@nitra/cursor/rules/worktree/fix.mjs'
|
|
99
|
-
|
|
100
|
-
const ctx = { walkCache: new Map(/* ... */) }
|
|
101
|
-
const exitCode = await run(ctx)
|
|
102
|
-
// exitCode === 0 — OK, 1 — порушення
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Послідовність:
|
|
106
|
-
|
|
107
|
-
1. Оркестратор (`@nitra/cursor fix` без аргументів або з переліком правил) проходить по списку правил і для кожного робить `import('.../fix.mjs')`.
|
|
108
|
-
2. Викликає `run(sharedCtx)`, де `sharedCtx.walkCache` спільний для всіх правил у прогоні (економить FS-обходи).
|
|
109
|
-
3. `run` делегує в `runStandardRule(import.meta.dirname, ctx)`.
|
|
110
|
-
4. `runStandardRule` послідовно виконує під-кроки правила `worktree`: `applies` → JS-перевірки → `policy` → `mdc-refs`.
|
|
111
|
-
5. Повертається `number` (0/1), оркестратор агрегує результати всіх правил у фінальний summary.
|
|
112
|
-
|
|
113
|
-
Жодних `process.exit` у цьому сценарії — control flow залишається в оркестратора.
|
|
114
|
-
|
|
115
|
-
### Сценарій B — Standalone mode (прямий запуск)
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
bun npm/rules/worktree/fix.mjs
|
|
119
|
-
# або (еквівалент)
|
|
120
|
-
npx @nitra/cursor fix worktree
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
Послідовність:
|
|
124
|
-
|
|
125
|
-
1. Bun завантажує файл; `import.meta.url` вказує на сам файл як головний entry-point.
|
|
126
|
-
2. `isRunAsCli(import.meta.url)` повертає `true`.
|
|
127
|
-
3. Виконується `await runRuleCli(import.meta.dirname)`:
|
|
128
|
-
- читає проєктний config (`.cursor`/`package.json`);
|
|
129
|
-
- застосовує whitelist (включення/виключення файлів);
|
|
130
|
-
- формує `RuleContext` та викликає `run(ctx)` (опосередковано, через стандартний пайплайн);
|
|
131
|
-
- друкує summary в stdout (кількість порушень, перелік фейлів тощо).
|
|
132
|
-
4. `process.exit(<exitCode>)` — процес закривається з кодом для CI/IDE.
|
|
10
|
+
## Огляд
|
|
133
11
|
|
|
134
|
-
|
|
12
|
+
Виконує застосування політики JS-занепокоєних та конфігурації на наданому контексті прогону, генеруючи посилання MDC та повертаючи результат.
|
|
135
13
|
|
|
136
|
-
|
|
137
|
-
- Standalone mode зручний для **локальної налагодки** одного правила і для **IDE-інтеграцій** (Cursor запускає окремий `fix.mjs` й отримує exit-code).
|
|
138
|
-
- Логіка не дублюється — `runRuleCli` всередині все одно використовує той самий `runStandardRule`.
|
|
14
|
+
Виконується при запуску через командний рядок, виконуючи повний еквівалент команди `npx @nitra/cursor fix <id>`, завантажуючи конфігурацію, перевіряючи дозволені елементи та генеруючи зведену інформацію з виходом з процесу залежно від результату.
|
|
139
15
|
|
|
140
|
-
|
|
16
|
+
## Поведінка
|
|
141
17
|
|
|
142
|
-
|
|
18
|
+
1. Запуск правила.
|
|
19
|
+
* Приймає контекст прогону.
|
|
20
|
+
* Виконує застосування JS-занепокоєних.
|
|
21
|
+
* Застосовує політику.
|
|
22
|
+
* Генерує посилання MDC.
|
|
23
|
+
* Повертає результат прогону.
|
|
143
24
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
25
|
+
2. Запуск у режимі CLI.
|
|
26
|
+
* Виконується при запуску через CLI.
|
|
27
|
+
* Виконує повний еквівалент команди `npx @nitra/cursor fix <id>`.
|
|
28
|
+
* Виконує завантаження конфігурації.
|
|
29
|
+
* Виконує перевірку дозволених елементів.
|
|
30
|
+
* Генерує зведену інформацію.
|
|
31
|
+
* Виконує вихід з процесу залежно від результату.
|
|
149
32
|
|
|
150
|
-
|
|
33
|
+
## Публічний API
|
|
151
34
|
|
|
152
|
-
|
|
35
|
+
run — запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
36
|
+
Library mode — викликається CLI orchestration через `import + run`.
|
|
153
37
|
|
|
154
|
-
|
|
38
|
+
## Гарантії поведінки
|
|
155
39
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
4. **Eslint-disable коментар:** перед `process.exit` — `// eslint-disable-next-line n/no-process-exit, unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE`.
|
|
160
|
-
5. **Коментарі:** перед `if`-блоком — пояснення про standalone-режим та еквівалентність `npx @nitra/cursor fix <id>`; над `run` — JSDoc про послідовність applies → JS-concerns → policy → mdc-refs та library mode.
|
|
161
|
-
6. **Стиль:** ESM, без `;` у кінці рядків, single quotes, без default-експортів.
|
|
40
|
+
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
41
|
+
- Кешує результати в межах одного прогону.
|
|
42
|
+
- Не звертається до мережі.
|