@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,98 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
docgen:
|
|
3
|
+
source: npm/rules/npm-module/fix.mjs
|
|
4
|
+
crc: 38cf876b
|
|
5
|
+
score: 100
|
|
6
|
+
---
|
|
2
7
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
`fix.mjs` — мінімалістична точка входу (entry-point) для правила з ідентифікатором, що відповідає назві теки, у якій файл розташований (`npm/rules/npm-module/`). Файл виконує дві ролі одночасно:
|
|
6
|
-
|
|
7
|
-
1. **Library mode** — експортує функцію `run(ctx)`, яку викликає оркестратор `npm/scripts/lib/run-standard-rule.mjs` через стандартний імпорт. Це дозволяє іншому коду (наприклад, агрегатору правил `@nitra/cursor`) виконувати правило у складі загального прогону.
|
|
8
|
-
2. **Standalone mode** — якщо файл стартує напряму (наприклад, `bun npm/rules/npm-module/fix.mjs`), він прогорає еквівалент команди `npx @nitra/cursor fix npm-module` через `runRuleCli` із завантаженням конфігу, whitelist та фінальним summary; повертає у процес коректний exit-code для CI/IDE.
|
|
9
|
-
|
|
10
|
-
Логіки самого правила тут немає — файл лише делегує виконання у стандартний раннер `runStandardRule`, який послідовно проганяє чотири фази правила: `applies` → `JS-concerns` → `policy` → `mdc-refs`.
|
|
11
|
-
|
|
12
|
-
## Експорти / API
|
|
13
|
-
|
|
14
|
-
| Назва | Тип | Призначення |
|
|
15
|
-
| ----- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
16
|
-
| `run` | `function (ctx?) => Promise<number>` | Іменований експорт для library-mode. Викликає `runStandardRule` зі шляхом до теки правила та опційним контекстом. Повертає Promise з exit-кодом: `0` — правило не зафіксувало порушень, `1` — є порушення. |
|
|
17
|
-
|
|
18
|
-
Дефолтних експортів немає. Side-effect верхнього рівня: за умови запуску як CLI, наприкінці модуля викликається `process.exit(...)` з кодом, який повернув `runRuleCli`.
|
|
19
|
-
|
|
20
|
-
## Функції (сигнатура / параметри / повертає / side effects)
|
|
21
|
-
|
|
22
|
-
### `run(ctx)`
|
|
23
|
-
|
|
24
|
-
```js
|
|
25
|
-
export function run(ctx)
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
- **Параметри**
|
|
29
|
-
- `ctx` _(опційний)_ — об'єкт типу `RuleContext`, імпортований з `../../scripts/lib/run-standard-rule.mjs`. Може містити, зокрема, `walkCache` (закешований обхід дерева файлів), щоб уникнути повторного walk при паралельному прогоні кількох правил.
|
|
30
|
-
- **Повертає** `Promise<number>`:
|
|
31
|
-
- `0` — правило не виявило порушень або не застосовується до поточного workspace.
|
|
32
|
-
- `1` — зафіксовано принаймні одне порушення.
|
|
33
|
-
- **Side effects**
|
|
34
|
-
- Жодних прямих побічних ефектів у самій `run`. Усі побічні ефекти (читання файлів, друк summary, мутація `walkCache`) — у `runStandardRule` та підлеглих фазах правила.
|
|
35
|
-
- **Реалізація**
|
|
36
|
-
|
|
37
|
-
```js
|
|
38
|
-
return runStandardRule(import.meta.dirname, ctx)
|
|
39
|
-
```
|
|
8
|
+
# fix.mjs
|
|
40
9
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
### Standalone-блок (без іменованої функції)
|
|
44
|
-
|
|
45
|
-
```js
|
|
46
|
-
if (isRunAsCli(import.meta.url)) {
|
|
47
|
-
process.exit(await runRuleCli(import.meta.dirname))
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
- **Умова** — `isRunAsCli(import.meta.url)` повертає `true`, якщо модуль є точкою входу процесу (а не імпортується іншим модулем).
|
|
52
|
-
- **Дія** — `await runRuleCli(import.meta.dirname)` виконує повний CLI-цикл (config-loading, whitelist, прогін правила, summary) і повертає exit-код. Цей код передається у `process.exit`.
|
|
53
|
-
- **Коментар у коді** свідомо вимикає правила лінтера `n/no-process-exit` та `unicorn/no-process-exit`, оскільки standalone-entry-point має повертати exit-код для CI/IDE.
|
|
54
|
-
|
|
55
|
-
## Залежності
|
|
56
|
-
|
|
57
|
-
Прямі (внутрішні) залежності — два модулі зі спільної бібліотеки скриптів проєкту:
|
|
58
|
-
|
|
59
|
-
| Шлях імпорту | Що бере | Призначення |
|
|
60
|
-
| ----------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
61
|
-
| `../../scripts/lib/run-rule-cli.mjs` | `isRunAsCli`, `runRuleCli` | Допоміжна логіка для роботи у standalone-режимі: визначення, чи модуль є entry-point процесу, і запуск повного CLI-циклу правила, який є еквівалентом `npx @nitra/cursor fix <id>`. |
|
|
62
|
-
| `../../scripts/lib/run-standard-rule.mjs` | `runStandardRule`, тип `RuleContext` (через JSDoc) | Уніфікований раннер чотирифазного правила (`applies → JS-concerns → policy → mdc-refs`). Через нього прогрівається walk-cache і виконуються фази у фіксованому порядку. |
|
|
63
|
-
|
|
64
|
-
Зовнішніх (npm) залежностей файл не має. Він спирається на Node.js / Bun рантайм-можливості:
|
|
65
|
-
|
|
66
|
-
- `import.meta.url` — для визначення, чи модуль запущений як CLI.
|
|
67
|
-
- `import.meta.dirname` — для отримання абсолютного шляху до теки правила.
|
|
68
|
-
- `process.exit` — для повернення exit-коду у standalone-режимі.
|
|
69
|
-
|
|
70
|
-
## Потік виконання / Використання
|
|
71
|
-
|
|
72
|
-
### Сценарій A: Library mode (через оркестратор `@nitra/cursor`)
|
|
10
|
+
## Огляд
|
|
73
11
|
|
|
74
|
-
|
|
75
|
-
2. `isRunAsCli(import.meta.url)` повертає `false` (модуль не є entry-point) — standalone-блок ігнорується.
|
|
76
|
-
3. Оркестратор викликає `await mod.run(ctx)`, передаючи спільний `RuleContext` (наприклад, з заздалегідь побудованим `walkCache`).
|
|
77
|
-
4. `run` делегує виконання `runStandardRule(import.meta.dirname, ctx)`, який проганяє чотири фази правила і повертає `0` або `1`.
|
|
78
|
-
5. Оркестратор агрегує exit-коди всіх правил у фінальний код процесу.
|
|
12
|
+
Виконує обробку JS-занепокоєних на наданому контексті прогону, застосовує політику [Політика_X] та генерує посилання MDC.
|
|
79
13
|
|
|
80
|
-
|
|
14
|
+
## Поведінка
|
|
81
15
|
|
|
82
|
-
1.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
16
|
+
1. Запуск правила.
|
|
17
|
+
* Приймає контекст прогону.
|
|
18
|
+
* Виконує застосування JS-занепокоєних.
|
|
19
|
+
* Застосовує політику.
|
|
20
|
+
* Генерує посилання MDC.
|
|
21
|
+
* Повертає результат прогону.
|
|
22
|
+
2. Виконання у режимі CLI.
|
|
23
|
+
* Виконується як автономний скрипт.
|
|
24
|
+
* Виконує повний еквівалент команди `npx @nitra/cursor fix <id>`.
|
|
25
|
+
* Повертає код виходу з процесу.
|
|
90
26
|
|
|
91
|
-
|
|
27
|
+
## Публічний API
|
|
92
28
|
|
|
93
|
-
|
|
29
|
+
run — запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
30
|
+
Library mode — викликається CLI orchestration через `import + run`.
|
|
94
31
|
|
|
95
|
-
|
|
96
|
-
- Standalone-блок навпаки відповідає за повноцінний CLI-UX: завантаження конфігу, whitelist, summary, exit-code — усе, що очікується від `fix.mjs` правила, який запускається окремо.
|
|
32
|
+
## Гарантії поведінки
|
|
97
33
|
|
|
98
|
-
|
|
34
|
+
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
35
|
+
- Кешує результати в межах одного прогону.
|
|
36
|
+
- Не звертається до мережі.
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
---
|
|
2
2
|
docgen:
|
|
3
3
|
source: npm/rules/npm-module/js/header_doc_pointer.mjs
|
|
4
|
-
crc:
|
|
4
|
+
crc: d96a2957
|
|
5
|
+
score: 100
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# header_doc_pointer.mjs
|
|
8
9
|
|
|
9
10
|
## Огляд
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
Файл виконує перевірку документації для модулів. Сканує директорії npm/rules та npm/skills. Перевіряє наявність файлів docs/<stem>.md у піддиректоріях правил/скілів. Перевіряє, чи містить відповідні js-файли не більше одного рядка JSDoc. У разі перевищення ліміту, генерує звіт про порушення.
|
|
12
13
|
|
|
13
14
|
## Поведінка
|
|
14
15
|
|
|
15
|
-
1.
|
|
16
|
-
2. Для
|
|
17
|
-
3.
|
|
18
|
-
4. Якщо
|
|
19
|
-
5.
|
|
16
|
+
1. Сканувати директорії npm/rules та npm/skills.
|
|
17
|
+
2. Для кожної директорії перевіряти піддиректорії правил/скілів.
|
|
18
|
+
3. Для кожного знайденого js-файлу перевіряти наявність файлу docs/<stem>.md.
|
|
19
|
+
4. Якщо файл docs/<stem>.md існує, перевіряти, чи містить module-level JSDoc не більше одного непорожного рядка.
|
|
20
|
+
5. У разі перевищення ліміту, зарепортувати порушення.
|
|
21
|
+
6. Повертати код виходу репортера.
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
## Публічний API
|
|
22
24
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
25
|
+
- check — сканує файли `npm/rules/*/js/*.mjs` та `npm/skills/*/js/*.mjs`.
|
|
26
|
+
- Якщо існує `docs/<stem>.md`, модуль повинен мати посилання на JSDoc (не наратив).
|
|
27
|
+
- Якщо `docs` відсутній, обмеження не застосовуються.
|
|
26
28
|
|
|
27
29
|
## Гарантії поведінки
|
|
28
30
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
- Тестові файли (`*.test.mjs`) не скануються.
|
|
32
|
-
- Підкаталоги `tests/`, `data/`, `templates/` у `js/` не скануються (discovery бере лише `*.mjs` безпосередньо в `js/`, не рекурсивно).
|
|
31
|
+
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
32
|
+
- Не звертається до мережі.
|
|
@@ -1,274 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
docgen:
|
|
3
|
+
source: npm/rules/npm-module/js/package_structure.mjs
|
|
4
|
+
crc: 943e3b76
|
|
5
|
+
score: 85
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# package_structure.mjs
|
|
2
9
|
|
|
3
10
|
## Огляд
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Модуль підтримує два альтернативні layout-и npm-модуля:
|
|
8
|
-
|
|
9
|
-
1. **`npm/src` + `.js`-файли** — канонічний layout зі згенерованим `npm/types/index.d.ts` через `tsc` з прапорцями `--declaration --allowJs --emitDeclarationOnly --outDir types --skipLibCheck`.
|
|
10
|
-
2. **`npm/tsconfig.emit-types.json`** — коли `.js`-файлів під `npm/src` немає; типи виганяються через `tsc -p tsconfig.emit-types.json`.
|
|
11
|
-
|
|
12
|
-
Окремо модуль контролює, щоб опублікований пакет (`npm pack`) не містив тестів і фікстур: сканує каталог `npm/` за полем `"files"` з `package.json` (з урахуванням негативних glob-патернів) і відсіює test-style каталоги, імена файлів та AST-імпорти test-фреймворків.
|
|
13
|
-
|
|
14
|
-
Деякі перевірки (структура `npm/package.json`, валідація `compilerOptions` у `tsconfig.emit-types.json`, валідація полів `npm-publish.yml`) делеговані Rego-полісі у `npm/policy/npm_module/`. У цьому файлі лишається лише cross-file / FS / AST-частина: чи реально існує файл на диску, чи містить опублікований tarball тести, чи має `hk.pkl` правильні підрядки команди `tsc`.
|
|
15
|
-
|
|
16
|
-
Узгодженість `version`/`CHANGELOG.md` у файлі **не** перевіряється — це робить `changelog/js/consistency.mjs` за моделлю `n-changelog.mdc`.
|
|
17
|
-
|
|
18
|
-
## Експорти / API
|
|
19
|
-
|
|
20
|
-
| Експорт | Тип | Призначення |
|
|
21
|
-
| ----------------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
22
|
-
| `globToRegex(glob)` | `function` | Перетворює glob-патерн на `RegExp` із якорями `^` / `$`; підтримує `**`, `*`, `?`, `{a,b,c}`. |
|
|
23
|
-
| `findTestFrameworkImport(content, virtualPath)` | `async function` | Парсить JS/TS через `oxc-parser` і повертає назву модуля test-фреймворку, якщо знайдено import / require / dynamic import. |
|
|
24
|
-
| `classifyPublishedFileAsTest(relPath, cwd?)` | `async function` | Класифікує файл як test/fixture за каталогом, basename або AST-імпортом. |
|
|
25
|
-
| `check(cwd?)` | `async function` | Головна точка входу checker-а правила `npm-module.mdc`; повертає exit-code `0` / `1`. |
|
|
26
|
-
|
|
27
|
-
Решта функцій (`npmSrcTreeHasJsFile`, `readHkConfig`, `missingHkSrcLayoutFragments`, `missingHkEmitTypesConfigFragments`, `npmTypesFileFromPackageField`, `checkNpmPackageJson`, `checkEmitTypesConfig`, `checkPublishWorkflow`, `collectPublishedFiles`, `checkNoTestsInPublishedFiles`, `checkNpmModuleBasicStructure`) — приватні для модуля.
|
|
28
|
-
|
|
29
|
-
## Константи
|
|
30
|
-
|
|
31
|
-
| Константа | Значення / Опис |
|
|
32
|
-
| ------------------------ | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
33
|
-
| `EMIT_TYPES_CONFIG` | `'npm/tsconfig.emit-types.json'` — шлях до TS-config для emit без `src`. |
|
|
34
|
-
| `TEST_DIR_NAMES` | `Set` з `'tests'`, `'__tests__'`, `'fixtures'`, `'__fixtures__'`, `'spec'`, `'test'`. |
|
|
35
|
-
| `TEST_FILE_PATTERNS` | `[/^.+\.(test | spec)\.[cm]?[jt]sx?$/iu]` — патерн test-файлів за basename. Rego-файли (`\*\_test.rego`) свідомо не входять (conftest-конвенція). |
|
|
36
|
-
| `JS_LIKE_EXT_RE` | `/\.[cm]?[jt]sx?$/iu` — розширення, у яких сканується AST на імпорти test-фреймворків. |
|
|
37
|
-
| `TEST_FRAMEWORK_MODULES` | `Set` з `'bun:test'`, `'node:test'`, `'vitest'`, `'@jest/globals'`, `'jest'`, `'mocha'`, `'ava'`, `'tap'`, `'tape'`. |
|
|
38
|
-
| `REGEX_SPECIAL_IN_GLOB` | `Set` спецсимволів regex, які екрануються у glob-сегменті (без `*`/`?`). |
|
|
39
|
-
| `GLOBSTAR_LEADING_RE` | `/^__GLOBSTAR__\//u` — маркер `**/` на початку. |
|
|
40
|
-
| `GLOBSTAR_TRAILING_RE` | `/\/__GLOBSTAR__$/u` — маркер `/**` у кінці. |
|
|
41
|
-
|
|
42
|
-
## Функції
|
|
43
|
-
|
|
44
|
-
### `npmSrcTreeHasJsFile(cwd, ignorePaths = [])`
|
|
45
|
-
|
|
46
|
-
- **Сигнатура:** `async (cwd: string, ignorePaths?: string[]) => Promise<boolean>`
|
|
47
|
-
- **Параметри:**
|
|
48
|
-
- `cwd` — корінь репозиторію.
|
|
49
|
-
- `ignorePaths` — абсолютні шляхи каталогів, повністю виключених з обходу (з `loadCursorIgnorePaths`).
|
|
50
|
-
- **Повертає:** `true`, якщо хоча б один `.js` під `npm/src` (рекурсивно); інакше `false`. Якщо `npm/src` не існує — одразу `false`.
|
|
51
|
-
- **Side effects:** жодних (тільки FS-читання).
|
|
52
|
-
|
|
53
|
-
### `readHkConfig(cwd)`
|
|
54
|
-
|
|
55
|
-
- **Сигнатура:** `async (cwd: string) => Promise<{ path: string, text: string } | null>`
|
|
56
|
-
- **Параметри:** `cwd` — корінь репозиторію.
|
|
57
|
-
- **Повертає:** обʼєкт із relative-шляхом (`hk.pkl` або `.config/hk.pkl`) і повним текстом файлу; `null`, якщо жоден кандидат не існує.
|
|
58
|
-
- **Side effects:** читання файлу через `readFile`.
|
|
59
|
-
|
|
60
|
-
### `missingHkSrcLayoutFragments(hkText)`
|
|
61
|
-
|
|
62
|
-
- **Сигнатура:** `(hkText: string) => string[]`
|
|
63
|
-
- **Параметри:** `hkText` — текст hk-конфігурації.
|
|
64
|
-
- **Повертає:** список фрагментів, яких немає в тексті. Очікувані фрагменти: `["pre-commit"]`, `bunx -p typescript tsc`, `src/**/*.js`, `--declaration`, `--allowJs`, `--emitDeclarationOnly`, `--outDir types`, `--skipLibCheck`.
|
|
65
|
-
- **Side effects:** немає.
|
|
66
|
-
|
|
67
|
-
### `missingHkEmitTypesConfigFragments(hkText)`
|
|
68
|
-
|
|
69
|
-
- **Сигнатура:** `(hkText: string) => string[]`
|
|
70
|
-
- **Параметри:** `hkText` — текст hk-конфігурації.
|
|
71
|
-
- **Повертає:** список відсутніх фрагментів для layout-у через `tsconfig.emit-types.json`: `["pre-commit"]`, `bunx -p typescript tsc`, `tsconfig.emit-types.json`.
|
|
72
|
-
- **Side effects:** немає.
|
|
73
|
-
|
|
74
|
-
### `npmTypesFileFromPackageField(typesField)`
|
|
75
|
-
|
|
76
|
-
- **Сигнатура:** `(typesField: unknown) => string | null`
|
|
77
|
-
- **Параметри:** `typesField` — значення поля `types` з `npm/package.json`.
|
|
78
|
-
- **Повертає:** posix-шлях `npm/<rel>` (наприклад, `npm/types/bin/x.d.ts`) або `null`, якщо значення не починається з `./types/` чи не є рядком.
|
|
79
|
-
- **Side effects:** немає.
|
|
80
|
-
|
|
81
|
-
### `checkNpmPackageJson(useSrcJsLayout, passFn, failFn, cwd)`
|
|
82
|
-
|
|
83
|
-
- **Сигнатура:** `async (useSrcJsLayout: boolean, passFn, failFn, cwd: string) => Promise<void>`
|
|
84
|
-
- **Поведінка:**
|
|
85
|
-
- Якщо `npm/package.json` відсутній — нічого не робить (вище у потоці це вже відловлено).
|
|
86
|
-
- Для layout `src+js`: очікує існування `npm/types/index.d.ts`.
|
|
87
|
-
- Для layout `emit-types`: бере `npm/<types-field>` і перевіряє існування.
|
|
88
|
-
- **Викликає:** `passFn(msg)` при успіху, `failFn(msg)` при помилці.
|
|
89
|
-
- **Side effects:** читає `npm/package.json`.
|
|
90
|
-
|
|
91
|
-
### `checkEmitTypesConfig(passFn, failFn, cwd)`
|
|
92
|
-
|
|
93
|
-
- **Сигнатура:** `(passFn, failFn, cwd: string) => void`
|
|
94
|
-
- **Поведінка:** перевіряє лише існування `npm/tsconfig.emit-types.json`. Структуру `compilerOptions` валідує Rego-полісі `npm_module/emit_types_config`.
|
|
95
|
-
|
|
96
|
-
### `checkPublishWorkflow(passFn, failFn, cwd)`
|
|
97
|
-
|
|
98
|
-
- **Сигнатура:** `(passFn, failFn, cwd: string) => void`
|
|
99
|
-
- **Поведінка:** перевіряє лише існування `.github/workflows/npm-publish.yml`. Структуру полів workflow валідує Rego-полісі `npm_module/npm_publish_yml`.
|
|
100
|
-
|
|
101
|
-
### `globToRegex(glob)` (експортована)
|
|
102
|
-
|
|
103
|
-
- **Сигнатура:** `(glob: string) => RegExp`
|
|
104
|
-
- **Параметри:** `glob` — posix-шлях у glob-нотації.
|
|
105
|
-
- **Повертає:** `RegExp` з якорями `^` / `$` і прапорцем `u`.
|
|
106
|
-
- **Підтримка синтаксису:**
|
|
107
|
-
- `**` — нуль або більше сегментів (`(?:/.*/|/)` між сегментами, `(?:.*/)?` на початку, `(?:/.*)?` у кінці, `.*` як єдиний токен).
|
|
108
|
-
- `*` — будь-які символи без `/` (`[^/]*`).
|
|
109
|
-
- `?` — один символ без `/` (`[^/]`).
|
|
110
|
-
- `{a,b,c}` — brace-альтернативи (`(?:a|b|c)`).
|
|
111
|
-
- **Не підтримує:** клас `[…]` (для негативних патернів `files` цього достатньо).
|
|
112
|
-
- **Safety:** усі спецсимволи екрануються через `REGEX_SPECIAL_IN_GLOB`; eslint правило `security/detect-non-literal-regexp` явно вимкнено, бо вхід контрольований (поле `files` з `npm/package.json`).
|
|
113
|
-
|
|
114
|
-
### `collectPublishedFiles(filesField, cwd)`
|
|
115
|
-
|
|
116
|
-
- **Сигнатура:** `async (filesField: string[], cwd: string) => Promise<string[]>`
|
|
117
|
-
- **Параметри:**
|
|
118
|
-
- `filesField` — значення поля `files` з `npm/package.json`.
|
|
119
|
-
- `cwd` — корінь репозиторію.
|
|
120
|
-
- **Алгоритм:**
|
|
121
|
-
1. Розділяє patterns на позитивні і негативні (за префіксом `!`).
|
|
122
|
-
2. Для кожного позитивного pattern: якщо це файл — додає до `collected`; якщо директорія — рекурсивно через `walkDir` додає всі знайдені файли (posix-шляхи без `npm/` префікса).
|
|
123
|
-
3. Фільтрує: викидає файли, які матчать будь-який негативний `globToRegex`.
|
|
124
|
-
4. Сортує `[].sort()` (лексикографічно) і повертає.
|
|
125
|
-
- **Side effects:** `stat()` для кожного позитивного pattern, `walkDir` для директорій.
|
|
126
|
-
- **Обмеження:** не дублює всю логіку `npm pack` (LICENSE / README / mandatory files); сканує лише простір імен `files`.
|
|
127
|
-
|
|
128
|
-
### `findTestFrameworkImport(content, virtualPath)` (експортована)
|
|
129
|
-
|
|
130
|
-
- **Сигнатура:** `(content: string, virtualPath: string) => string | null`
|
|
131
|
-
- **Параметри:**
|
|
132
|
-
- `content` — повний текст файлу.
|
|
133
|
-
- `virtualPath` — шлях файлу (для вибору `lang` через `langFromPath`).
|
|
134
|
-
- **Повертає:** ім'я модуля test-фреймворку (з `TEST_FRAMEWORK_MODULES`), якщо знайдено; `null` інакше.
|
|
135
|
-
- **Алгоритм:**
|
|
136
|
-
1. Парсить через `parseSync` із `oxc-parser`; при помилці парсингу — повертає `null` (це не AST-checker для синтаксису).
|
|
137
|
-
2. Якщо `result.errors.length` ≠ 0 — повертає `null`.
|
|
138
|
-
3. Спочатку перевіряє `result.module.staticImports`.
|
|
139
|
-
4. Якщо в static-import не знайдено — обходить AST через `walkAstWithAncestors` і шукає `require(...)` (через `requireCallModule`) та `import(...)` dynamic (через `dynamicImportModule`).
|
|
140
|
-
- **Side effects:** немає.
|
|
141
|
-
|
|
142
|
-
### `classifyPublishedFileAsTest(relPath, cwd = process.cwd())` (експортована)
|
|
143
|
-
|
|
144
|
-
- **Сигнатура:** `async (relPath: string, cwd?: string) => Promise<string | null>`
|
|
145
|
-
- **Параметри:**
|
|
146
|
-
- `relPath` — posix-шлях відносно `npm/`.
|
|
147
|
-
- `cwd` — корінь репозиторію (за замовчуванням `process.cwd()`).
|
|
148
|
-
- **Повертає:** рядок-причину порушення або `null`, якщо файл валідний.
|
|
149
|
-
- **Класифікація (за пріоритетом):**
|
|
150
|
-
1. У path є сегмент із `TEST_DIR_NAMES` → `'test-style каталог "<seg>/"'`.
|
|
151
|
-
2. Basename матчить `TEST_FILE_PATTERNS` → `"test-style ім'я файлу"`.
|
|
152
|
-
3. Розширення JS-like і AST містить імпорт test-фреймворку → `'імпорт test-фреймворку "<mod>"'`.
|
|
153
|
-
- **Carve-out:** для `rules/<rule-name>/...` сегмент `<rule-name>` (індекс 1) ігнорується, бо це ім'я правила (наприклад, правило з id `test` саме описує конвенцію тестів і не є fixture-каталогом). Подальші сегменти (`rules/<r>/js/<c>/tests/`) продовжують перевірятись.
|
|
154
|
-
- **Side effects:** для JS-like розширень — `readFile(join(cwd, 'npm', relPath))`.
|
|
155
|
-
|
|
156
|
-
### `checkNoTestsInPublishedFiles(pass, fail, cwd)`
|
|
157
|
-
|
|
158
|
-
- **Сигнатура:** `async (pass, fail, cwd: string) => Promise<void>`
|
|
159
|
-
- **Поведінка:**
|
|
160
|
-
- Якщо `npm/package.json` відсутній або поле `files` не масив — нічого не робить.
|
|
161
|
-
- Інакше збирає файли через `collectPublishedFiles` і прогонить кожен через `classifyPublishedFileAsTest`.
|
|
162
|
-
- На порушення викликає `fail(...)` з підказкою додати негативний glob у `files`.
|
|
163
|
-
- На повну чистоту — `pass(...)` з кількістю перевірених файлів.
|
|
164
|
-
|
|
165
|
-
### `checkNpmModuleBasicStructure(pass, fail, cwd)`
|
|
166
|
-
|
|
167
|
-
- **Сигнатура:** `async (pass, fail, cwd: string) => Promise<void>`
|
|
168
|
-
- **Поведінка:** перевіряє наявність `package.json`, директорії `npm/` і `npm/package.json`. Поле `workspaces ∋ "npm"` у кореневому `package.json` валідує Rego.
|
|
169
|
-
|
|
170
|
-
### `check(cwd = process.cwd())` (експортована, головна)
|
|
171
|
-
|
|
172
|
-
- **Сигнатура:** `async (cwd?: string) => Promise<number>`
|
|
173
|
-
- **Повертає:** `0` — все OK, `1` — є проблеми (через `reporter.getExitCode()`).
|
|
174
|
-
- **Алгоритм:**
|
|
175
|
-
1. Створює `createCheckReporter()`, дістає `pass`, `fail`.
|
|
176
|
-
2. `checkNpmModuleBasicStructure` — `package.json`, `npm/`, `npm/package.json`.
|
|
177
|
-
3. `checkNoTestsInPublishedFiles` — компактність tarball.
|
|
178
|
-
4. `loadCursorIgnorePaths(cwd)` для подальшого скану `npm/src`.
|
|
179
|
-
5. `npmSrcTreeHasJsFile` → визначає `useSrcJsLayout`.
|
|
180
|
-
6. `checkNpmPackageJson(useSrcJsLayout, ...)` — поле `types` і відповідний файл на диску.
|
|
181
|
-
7. Якщо НЕ `useSrcJsLayout` — `checkEmitTypesConfig`.
|
|
182
|
-
8. `readHkConfig` → знайти hk; перевірити pre-commit-фрагменти через `missingHkSrcLayoutFragments` або `missingHkEmitTypesConfigFragments` залежно від layout.
|
|
183
|
-
9. `.github/workflows/` існує.
|
|
184
|
-
10. `checkPublishWorkflow` — `npm-publish.yml`.
|
|
185
|
-
11. `return reporter.getExitCode()`.
|
|
186
|
-
|
|
187
|
-
## Залежності
|
|
188
|
-
|
|
189
|
-
### Node.js core
|
|
190
|
-
|
|
191
|
-
- `node:fs` — `existsSync`.
|
|
192
|
-
- `node:fs/promises` — `readFile`, `stat`.
|
|
193
|
-
- `node:path` — `join`, `sep`.
|
|
194
|
-
|
|
195
|
-
### Зовнішні npm
|
|
196
|
-
|
|
197
|
-
- `oxc-parser` — `parseSync` для AST-парсингу JS/TS у `findTestFrameworkImport`.
|
|
198
|
-
|
|
199
|
-
### Внутрішні (relative)
|
|
200
|
-
|
|
201
|
-
- `../../../scripts/utils/ast-scan-utils.mjs` — `dynamicImportModule`, `langFromPath`, `requireCallModule`, `walkAstWithAncestors`.
|
|
202
|
-
- `../../../scripts/lib/check-reporter.mjs` — `createCheckReporter` (повертає `{ pass, fail, getExitCode }`).
|
|
203
|
-
- `../../../scripts/lib/load-cursor-config.mjs` — `loadCursorIgnorePaths` (читає `.cursorignore`-подібні шляхи).
|
|
204
|
-
- `../../../scripts/utils/walkDir.mjs` — `walkDir(root, callback, ignorePaths?)` для рекурсивного обходу.
|
|
205
|
-
|
|
206
|
-
## Потік виконання / Використання
|
|
207
|
-
|
|
208
|
-
### Базовий потік `check(cwd)`
|
|
209
|
-
|
|
210
|
-
```text
|
|
211
|
-
check(cwd)
|
|
212
|
-
├── createCheckReporter() → { pass, fail, getExitCode }
|
|
213
|
-
├── checkNpmModuleBasicStructure(pass, fail, cwd)
|
|
214
|
-
│ ├── existsSync(cwd/package.json) ? pass : fail
|
|
215
|
-
│ ├── existsSync(cwd/npm) && stat(...).isDirectory() ? pass : fail
|
|
216
|
-
│ └── existsSync(cwd/npm/package.json) ? pass : fail
|
|
217
|
-
├── checkNoTestsInPublishedFiles(pass, fail, cwd)
|
|
218
|
-
│ ├── readFile(npm/package.json) → pkg
|
|
219
|
-
│ ├── if !Array.isArray(pkg.files) → return
|
|
220
|
-
│ ├── files = collectPublishedFiles(pkg.files, cwd)
|
|
221
|
-
│ └── for rel of files: classifyPublishedFileAsTest(rel, cwd)
|
|
222
|
-
├── ignorePaths = loadCursorIgnorePaths(cwd)
|
|
223
|
-
├── useSrcJsLayout = npmSrcTreeHasJsFile(cwd, ignorePaths)
|
|
224
|
-
├── checkNpmPackageJson(useSrcJsLayout, pass, fail, cwd)
|
|
225
|
-
├── if !useSrcJsLayout → checkEmitTypesConfig(pass, fail, cwd)
|
|
226
|
-
├── hk = readHkConfig(cwd)
|
|
227
|
-
│ ├── hk == null → fail (потрібен hk.pkl)
|
|
228
|
-
│ └── inakshe →
|
|
229
|
-
│ missing = useSrcJsLayout
|
|
230
|
-
│ ? missingHkSrcLayoutFragments(hk.text)
|
|
231
|
-
│ : missingHkEmitTypesConfigFragments(hk.text)
|
|
232
|
-
│ missing.length === 0 ? pass : fail
|
|
233
|
-
├── existsSync(.github/workflows/) ? pass : fail
|
|
234
|
-
├── checkPublishWorkflow(pass, fail, cwd)
|
|
235
|
-
└── return reporter.getExitCode()
|
|
236
|
-
```
|
|
12
|
+
globToRegex
|
|
13
|
+
Перетворює glob-патерн у RegExp з якорями `^` та `$`.
|
|
237
14
|
|
|
238
|
-
|
|
15
|
+
findTestFrameworkImport
|
|
16
|
+
Знаходить імпорт модуля тест-фреймворку з контенту файлу.
|
|
239
17
|
|
|
240
|
-
|
|
18
|
+
classifyPublishedFileAsTest
|
|
19
|
+
Класифікує опублікований файл як test/fixture за ознаками.
|
|
241
20
|
|
|
242
|
-
|
|
21
|
+
check
|
|
22
|
+
Перевіряє відповідність проєкту правилам (npm-module.mdc).
|
|
243
23
|
|
|
244
|
-
|
|
245
|
-
- **Rego (`npm/policy/npm_module/`):**
|
|
246
|
-
- `npm_package_json` — структура `npm/package.json` (whitelist `files`, заборона `devDependencies`, тощо).
|
|
247
|
-
- `emit_types_config` — `compilerOptions` у `npm/tsconfig.emit-types.json`.
|
|
248
|
-
- `npm_publish_yml` — поля workflow (`on.push.paths`, `branches`, `id-token: write`, кроки JS-DevTools/npm-publish), парсяться після YAML-parse.
|
|
249
|
-
- `root_package_json` — `workspaces ∋ "npm"` у кореневому `package.json`.
|
|
24
|
+
## Поведінка
|
|
250
25
|
|
|
251
|
-
|
|
26
|
+
globToRegex
|
|
27
|
+
Перетворює glob-патерн у RegExp з якорями `^` / `$`.
|
|
252
28
|
|
|
253
|
-
|
|
254
|
-
|
|
29
|
+
findTestFrameworkImport
|
|
30
|
+
Знаходить імпорт модуля тест-фреймворку з контенту файлу.
|
|
255
31
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
```
|
|
32
|
+
classifyPublishedFileAsTest
|
|
33
|
+
Класифікує опублікований файл як test/fixture за ознаками.
|
|
259
34
|
|
|
260
|
-
|
|
35
|
+
check
|
|
36
|
+
Перевіряє відповідність проєкту правилам npm-module.mdc.
|
|
261
37
|
|
|
262
|
-
|
|
263
|
-
- Не валідує сам формат AST/синтаксис коду — за помилки парсингу `findTestFrameworkImport` мовчки повертає `null`.
|
|
264
|
-
- Не дублює логіку `npm pack` (LICENSE / README / mandatory files) — сканує лише простір імен `files`.
|
|
265
|
-
- Не перевіряє вміст Rego-полісі — лише дискову наявність / FS / AST.
|
|
38
|
+
## Публічний API
|
|
266
39
|
|
|
267
|
-
|
|
40
|
+
GlobToRegex — перетворює glob-патерн у RegExp з використанням `^` та `$`. Підтримує globstar, `*`, `?` та brace-альтернативи.
|
|
41
|
+
FindTestFrameworkImport — визначає наявність імпорту/require/dynamic-import модуля тест-фреймворку. Парсинг через oxc-parser повертає `null` у разі помилки.
|
|
42
|
+
ClassifyPublishedFileAsTest — відносить опублікований файл до test/fixture, якщо присутні ознаки: каталог з `TEST_DIR_NAMES`, збіг імені файлу з `TEST_FILE_PATTERNS`, або імпорт тест-фреймворку для JS/TS розширень.
|
|
43
|
+
Carve-out — витягує ім'я правила з шляху `rules/<rule-name>/...` (індекс 1), що позначає ім'я правила. Правило з id `test` або `tests` описує конвенцію розміщення тестів, але не є test-fixture. Подальші сегменти продовжують перевірку.
|
|
44
|
+
Check — перевіряє відповідність проєкту правилам npm-module.mdc.
|
|
268
45
|
|
|
269
|
-
|
|
46
|
+
## Гарантії поведінки
|
|
270
47
|
|
|
271
|
-
-
|
|
272
|
-
-
|
|
273
|
-
-
|
|
274
|
-
-
|
|
48
|
+
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
49
|
+
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
|
50
|
+
- За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
|
|
51
|
+
- Свідомо пропускає шляхи: `.github`, `.git`.
|
|
52
|
+
- Не звертається до мережі.
|