@nitra/cursor 5.1.0 → 5.2.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 +22 -0
- package/.pi-template/extensions/n-cursor-adr/docs/index.md +15 -9
- package/CHANGELOG.md +12 -1
- package/bin/n-cursor.js +73 -16
- package/docs/stryker.config.md +6 -0
- package/docs/vitest.config.md +6 -0
- package/lib/docs/llm.md +29 -0
- package/lib/docs/omlx.md +32 -0
- package/lib/llm.mjs +137 -0
- package/lib/omlx.mjs +49 -4
- package/package.json +1 -1
- package/rules/abie/docs/fix.md +6 -0
- package/rules/abie/js/docs/applies.md +6 -0
- package/rules/abie/js/docs/env_dns.md +25 -22
- package/rules/abie/js/docs/firebase_hosting.md +6 -0
- package/rules/abie/js/docs/hc_pairing.md +21 -25
- package/rules/abie/js/docs/ua_http_route.md +27 -19
- package/rules/abie/js/docs/ua_node_selector.md +24 -19
- package/rules/abie/lib/docs/enabled.md +13 -7
- package/rules/abie/lib/docs/env-dns.md +9 -3
- package/rules/abie/lib/docs/hc-yaml.md +6 -0
- package/rules/abie/lib/docs/http-route.md +6 -0
- package/rules/abie/lib/docs/k8s-tree.md +6 -0
- package/rules/abie/lib/docs/kustomization-patches.md +6 -0
- package/rules/abie/lib/docs/overlay-paths.md +6 -0
- package/rules/abie/lib/docs/yaml.md +6 -0
- package/rules/adr/docs/fix.md +6 -0
- package/rules/adr/js/docs/hooks.md +29 -244
- package/rules/bun/docs/fix.md +6 -0
- package/rules/bun/js/docs/layout.md +37 -375
- package/rules/capacitor/docs/fix.md +22 -108
- package/rules/capacitor/js/docs/platforms.md +62 -268
- package/rules/changelog/docs/fix.md +6 -0
- package/rules/changelog/lib/docs/package-manifest.md +6 -0
- package/rules/ci4/docs/fix.md +23 -165
- package/rules/ci4/js/docs/marksman_config.md +9 -1
- package/rules/docker/docs/fix.md +6 -0
- package/rules/docker/js/docs/lint.md +55 -239
- package/rules/docker/lib/docs/docker-hadolint.md +6 -0
- package/rules/docker/lib/docs/docker-mirror.md +6 -0
- package/rules/docker/lib/docs/docker-native-addon.md +6 -0
- package/rules/docker/lib/docs/docker-nginx-user.md +6 -0
- package/rules/docker/lint/docs/lint.md +9 -1
- package/rules/efes/docs/fix.md +6 -0
- package/rules/ga/lint/docs/lint.md +6 -0
- package/rules/graphql/docs/fix.md +6 -0
- package/rules/graphql/lib/docs/graphql-gql-scan.md +6 -0
- package/rules/image-avif/docs/fix.md +6 -0
- package/rules/image-avif/js/docs/avif_generation.md +6 -0
- package/rules/js-bun-db/lib/docs/bun-sql-scan.md +9 -3
- package/rules/js-bun-redis/lib/docs/redis-imports.md +6 -0
- package/rules/js-lint/js/docs/utils_imports.md +6 -0
- package/rules/js-lint-ci/docs/fix.md +7 -1
- package/rules/js-mssql/docs/fix.md +6 -0
- package/rules/js-mssql/lib/docs/mssql-pool-scan.md +6 -0
- package/rules/js-run/docs/fix.md +6 -0
- package/rules/js-run/lib/docs/bunyan-imports.md +6 -0
- package/rules/js-run/lib/docs/check-env-scan.md +6 -0
- package/rules/js-run/lib/docs/conn-file-rules.md +6 -0
- package/rules/js-run/lib/docs/conn-imports-scan.md +6 -0
- package/rules/js-run/lib/docs/promise-settimeout-scan.md +6 -0
- package/rules/js-run/lib/docs/temporal-scan.md +6 -0
- package/rules/k8s/docs/fix.md +6 -0
- package/rules/k8s/lint/docs/lint.md +6 -0
- package/rules/nginx-default-tpl/docs/fix.md +6 -0
- package/rules/npm-module/js/docs/header_doc_pointer.md +7 -0
- package/rules/npm-module/js/header_doc_pointer.mjs +2 -8
- package/rules/php/docs/fix.md +6 -0
- package/rules/php/lint/docs/lint.md +6 -0
- package/rules/python/docs/fix.md +6 -0
- package/rules/python/lint/docs/lint.md +6 -0
- package/rules/rego/lint/docs/lint.md +6 -0
- package/rules/release/docs/change.md +6 -0
- package/rules/release/docs/fix.md +6 -0
- package/rules/release/docs/release.md +6 -0
- package/rules/release/lib/docs/aggregate.md +6 -0
- package/rules/release/lib/docs/change-file.md +6 -0
- package/rules/release/lib/docs/fallback.md +6 -0
- package/rules/rust/lib/docs/has-cargo-toml.md +6 -0
- package/rules/security/docs/fix.md +7 -1
- package/rules/security/js/docs/lint.md +6 -0
- package/rules/style-lint/docs/fix.md +6 -0
- package/rules/tauri/docs/fix.md +6 -0
- package/rules/test/docs/fix.md +6 -0
- package/rules/test/js/data/stryker_config/docs/stryker-vue-macros-ignorer.md +6 -0
- package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +6 -0
- package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +6 -0
- package/rules/test/js/data/vitest_config/docs/vitest.config.baseline.md +6 -0
- package/rules/text/docs/fix.md +6 -0
- package/rules/text/lint/docs/lint.md +6 -0
- package/rules/text/lint/docs/run-dotenv-linter.md +6 -0
- package/rules/text/lint/docs/run-shellcheck.md +6 -0
- package/rules/text/lint/docs/run-v8r.md +6 -0
- package/rules/vue/lib/docs/vue-forbidden-imports.md +6 -0
- package/scripts/coverage-classify/cache.mjs +1 -1
- package/scripts/coverage-classify/docs/apply.md +6 -0
- package/scripts/coverage-classify/docs/cache.md +6 -0
- package/scripts/coverage-classify/docs/prompt.md +6 -0
- package/scripts/coverage-classify/docs/verdict-schema.md +6 -0
- package/scripts/coverage-classify/prompt.mjs +1 -1
- package/scripts/coverage-fix-extract.mjs +1 -1
- package/scripts/coverage-fix.mjs +2 -1
- package/scripts/docs/auto-skills.md +6 -0
- package/scripts/docs/build-agents-commands.md +7 -1
- package/scripts/docs/cli-entry.md +6 -0
- package/scripts/docs/coverage-fix-extract.md +6 -0
- package/scripts/docs/coverage-fix.md +6 -0
- package/scripts/docs/ensure-nitra-cursor-dev-dependencies.md +6 -0
- package/scripts/docs/lint-cli.md +6 -0
- package/scripts/docs/post-tool-use-fix.md +6 -0
- package/scripts/docs/rename-yaml-extensions.md +6 -0
- package/scripts/docs/skills-cli.md +6 -0
- package/scripts/docs/sync-setup-bun-deps-action.md +6 -0
- package/scripts/docs/upgrade-nitra-cursor-and-install.md +6 -0
- package/scripts/docs/worktree-cli.md +6 -0
- package/scripts/lib/docs/assert-project-root.md +6 -0
- package/scripts/lib/docs/check-mdc-template-refs.md +6 -0
- package/scripts/lib/docs/check-reporter.md +6 -0
- package/scripts/lib/docs/diff-added-lines.md +6 -0
- package/scripts/lib/docs/discover-check-rules-from-cursor.md +6 -0
- package/scripts/lib/docs/discover-checkable-rules.md +6 -0
- package/scripts/lib/docs/ensure-tool.md +6 -0
- package/scripts/lib/docs/generated-markdown.md +6 -0
- package/scripts/lib/docs/gha-workflow.md +6 -0
- package/scripts/lib/docs/inline-template-links.md +6 -0
- package/scripts/lib/docs/list-rule-ids.md +6 -0
- package/scripts/lib/docs/load-cursor-config.md +6 -0
- package/scripts/lib/docs/mirror-parity.md +6 -0
- package/scripts/lib/docs/read-n-cursor-config-lite.md +6 -0
- package/scripts/lib/docs/resolve-target-files.md +6 -0
- package/scripts/lib/docs/root-notice.md +6 -0
- package/scripts/lib/docs/rule-meta-helpers.md +6 -0
- package/scripts/lib/docs/rule-meta.md +6 -0
- package/scripts/lib/docs/run-conftest-batch.md +6 -0
- package/scripts/lib/docs/run-lint-step.md +6 -0
- package/scripts/lib/docs/run-rule-cli.md +6 -0
- package/scripts/lib/docs/run-rule.md +6 -0
- package/scripts/lib/docs/run-standard-lint.md +6 -0
- package/scripts/lib/docs/run-standard-rule.md +6 -0
- package/scripts/lib/docs/skill-meta.md +6 -0
- package/scripts/lib/docs/template.md +6 -0
- package/scripts/lib/docs/timing-summary.md +6 -0
- package/scripts/lib/docs/workspaces.md +6 -0
- package/scripts/lib/docs/worktree-notice.md +6 -0
- package/scripts/lib/docs/worktree.md +6 -0
- package/scripts/lib/mirror-parity.mjs +1 -1
- package/scripts/lib/root-notice.mjs +1 -1
- package/scripts/lib/worktree-notice.mjs +5 -5
- package/scripts/lib/worktree.mjs +1 -1
- package/scripts/sync-claude-config.mjs +3 -0
- package/scripts/utils/docs/ast-scan-utils.md +6 -0
- package/scripts/utils/docs/ensure-gitignore-entries.md +6 -0
- package/scripts/utils/docs/find-package-json-paths.md +6 -0
- package/scripts/utils/docs/lock-cache-dir.md +6 -0
- package/scripts/utils/docs/pass.md +6 -0
- package/scripts/utils/docs/resolve-cargo-manifest.md +6 -0
- package/scripts/utils/docs/resolve-cmd.md +6 -0
- package/scripts/utils/docs/resolve-js-root.md +6 -0
- package/scripts/utils/docs/test-helpers.md +6 -0
- package/scripts/utils/docs/walk-cache.md +6 -0
- package/scripts/utils/docs/walkDir.md +6 -0
- package/scripts/utils/docs/worktree-fingerprint.md +6 -0
- package/scripts/utils/resolve-js-root.mjs +1 -1
- package/skills/doc-aggregate/SKILL.md +129 -0
- package/skills/doc-aggregate/js/docgen-ignore.mjs +9 -0
- package/skills/{docgen → doc-aggregate}/js/docgen-scan.mjs +22 -67
- package/skills/doc-aggregate/js/docs/docgen-ignore.md +21 -0
- package/skills/doc-files/SKILL.md +100 -0
- package/skills/doc-files/js/docgen-crc.mjs +164 -0
- package/skills/{docgen → doc-files}/js/docgen-extract-anchors.mjs +20 -11
- package/skills/{docgen → doc-files}/js/docgen-extract.mjs +15 -9
- package/skills/doc-files/js/docgen-files-batch.mjs +181 -0
- package/skills/doc-files/js/docgen-gen.mjs +291 -0
- package/skills/{docgen → doc-files}/js/docgen-prompts.mjs +43 -40
- package/skills/doc-files/js/docgen-scan.mjs +298 -0
- package/skills/doc-files/js/docs/docgen-crc.md +32 -0
- package/skills/doc-files/js/docs/docgen-extract-anchors.md +27 -0
- package/skills/doc-files/js/docs/docgen-extract.md +29 -0
- package/skills/doc-files/js/docs/docgen-files-batch.md +25 -0
- package/skills/doc-files/js/docs/docgen-gen.md +30 -0
- package/skills/doc-files/js/docs/docgen-prompts.md +32 -0
- package/skills/doc-files/js/docs/docgen-scan.md +25 -0
- package/skills/doc-files/meta.json +1 -0
- package/skills/fix/js/docs/llm-worker.md +6 -0
- package/skills/fix/js/docs/orchestrator.md +6 -0
- package/skills/fix/js/llm-worker.mjs +3 -3
- package/skills/fix/js/orchestrator.mjs +1 -1
- package/skills/start-check/js/check.mjs +5 -3
- package/skills/start-check/js/docs/check.md +6 -0
- package/skills/docgen/SKILL.md +0 -224
- package/skills/docgen/bench/etalon/firebase_hosting.md +0 -19
- package/skills/docgen/bench/etalon/k8s-tree.md +0 -24
- package/skills/docgen/bench/etalon/overlay-paths.md +0 -24
- package/skills/docgen/js/docgen-batch-omlx.mjs +0 -82
- package/skills/docgen/js/docgen-batch.mjs +0 -95
- package/skills/docgen/js/docgen-compare-pi-vs-direct.mjs +0 -95
- package/skills/docgen/js/docgen-gen.mjs +0 -306
- package/skills/docgen/js/docs/docgen-extract.md +0 -28
- package/skills/docgen/js/docs/docgen-gen.md +0 -41
- package/skills/docgen/js/docs/docgen-ignore.md +0 -24
- package/skills/docgen/js/docs/docgen-prompts.md +0 -24
- package/skills/docgen/js/docs/docgen-scan.md +0 -48
- /package/skills/{docgen → doc-aggregate}/meta.json +0 -0
- /package/skills/{docgen → doc-files}/js/docgen-ignore.mjs +0 -0
|
@@ -1,295 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
docgen:
|
|
3
|
+
source: npm/rules/capacitor/js/platforms.mjs
|
|
4
|
+
crc: eb8d6293
|
|
5
|
+
score: 100
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# platforms.mjs
|
|
2
9
|
|
|
3
10
|
## Огляд
|
|
4
11
|
|
|
5
|
-
Модуль
|
|
6
|
-
|
|
7
|
-
Перевірка послідовно виконує три блоки логіки:
|
|
8
|
-
|
|
9
|
-
1. **Виявлення Capacitor у репозиторії.** Capacitor вважається задіяним, якщо в корені присутній один із файлів `capacitor.config.json` / `capacitor.config.ts` / `capacitor.config.mjs`, **або** хоч у одному `package.json` (рекурсивний обхід дерева з пропуском типових каталогів) задекларовано пакет із префіксом `@capacitor/` у будь-якому блоці залежностей (`dependencies`, `devDependencies`, `optionalDependencies`, `peerDependencies`). Якщо ознак немає — check одразу повертає **pass** і код **0**, не вимагаючи жодних дій.
|
|
10
|
-
2. **Перевірка мінімальної версії `@capacitor/core` ≥ 8.** Для кожного `package.json`, який оголошує `@capacitor/core`, обчислюється **нижня межа major** з рядка npm-діапазону. Якщо вона менша за `MIN_CAPACITOR_MAJOR = 8`, або діапазон не вдалося визначити (`*`, `latest`, `x`, незрозумілий синтаксис) — це fail; повідомлення підказує задати, наприклад, `^8.0.0`. Якщо `capacitor.config.*` знайдено, а `@capacitor/core` у дереві відсутній — теж fail.
|
|
11
|
-
3. **iOS / Podfile.** За політикою `capacitor.mdc` iOS-частина Capacitor-застосунку повинна збиратися лише через **SPM**, без CocoaPods. Рекурсивний обхід `ios/` (пропускаючи `Pods`, `build`, `DerivedData`) шукає перший `Podfile`. Якщо `Podfile` є, він вважається порушенням, **окрім** випадку коли в кореневому `package.json` або в `capacitor.config.{json,ts,mjs}` присутній об’єкт `nitra` із прапором `iosCocoaPodsBecausePluginsLackSpm: true` або `iosCocoaPodsAllowed: true`. Якщо каталогу `ios/` немає — умова не застосовується.
|
|
12
|
-
|
|
13
|
-
Усі повідомлення про результат виводяться через `createCheckReporter()` зі спільного хелпера `scripts/lib/check-reporter.mjs`.
|
|
14
|
-
|
|
15
|
-
## Експорти / API
|
|
16
|
-
|
|
17
|
-
Файл експортує іменовані символи (без default export):
|
|
18
|
-
|
|
19
|
-
- `capacitorSegmentMinMajor(segment)` — мінімальний **major** для одного OR-сегмента npm-діапазону.
|
|
20
|
-
- `capacitorVersionRangeMinMajor(versionRange)` — мінімальний **major** для повного діапазону, з підтримкою `||`.
|
|
21
|
-
- `isCapacitorCoreVersionAtLeast8(versionRange, min?)` — булеан-предикат: чи нижня межа діапазону `≥ min` (за замовчуванням `MIN_CAPACITOR_MAJOR`).
|
|
22
|
-
- `recordCapacitorFromOnePackageJson(absPath, root, out)` — асинхронно прочитати один `package.json` і поповнити акумулятор.
|
|
23
|
-
- `collectCapacitorDataFromAllPackageJson(root, out)` — рекурсивно обійти всі `package.json` у репозиторії, агрегуючи `byPath` і `anyCapacitor`.
|
|
24
|
-
- `hasCapacitorConfigInRoot(root)` — синхронно перевірити наявність `capacitor.config.{json,ts,mjs}` у корені.
|
|
25
|
-
- `isCapacitorRelevantForCheck(root, anyCapacitor)` — чи варто застосовувати правила Capacitor взагалі.
|
|
26
|
-
- `walkIosForPodfileSkipPods(root, dir, onPodfileRelative)` — рекурсивний пошук `Podfile` під `ios/` із пропуском службових тек.
|
|
27
|
-
- `findFirstPodfileUnderIosExcludingPods(root)` — повертає **найкоротший** posix-relative шлях до першого знайденого `Podfile` (або `null`).
|
|
28
|
-
- `nitrAObjectAllowsIosCocoaPods(o)` — предикат для об’єкта `nitra`: чи дозволено CocoaPods.
|
|
29
|
-
- `check(cwd?)` — головна функція **check**; повертає **exit-код**.
|
|
30
|
-
|
|
31
|
-
Внутрішні (неекспортовані) функції: `firstVersionMajorFromNpmValue`, `reportOneCapacitorCoreRange`, `recordCapacitorFromDependencyObject`, `extractNitraObjectBodySource`, `nitraObjectBodyStringAllowsCocoaPodsExempt`, `pathJsonShowsNitraCocoapodsExempt`, `capacitorConfigTsMjsNitraCocoapodsExempt`, `isIosCocoaPodsExemptByNitraConfig`.
|
|
32
|
-
|
|
33
|
-
Константи модульного рівня:
|
|
34
|
-
|
|
35
|
-
- `MIN_CAPACITOR_MAJOR = 8` — мінімальний допустимий **major** Capacitor.
|
|
36
|
-
- `IGNORED_DIRS_FOR_PACKAGE_JSON` — `Set` каталогів, які пропускаються при обході (`node_modules`, `.git`, `dist`, `coverage`, `Pods`, `.turbo`, `.next`, `build`).
|
|
37
|
-
- Регулярки: `NPM_OR_PARTS_RE` (`\s*\|\|\s*`), `NPM_HYPHEN_RANGE_RE` (`^(.+?)\s+-\s+(.+)$`), `FIRST_VERSION_NUM_RE` (`^(?:v)?(\d+)`), `PREFIX_GEQ_RE` (`^>=\s*`), `PREFIX_GT_RE` (`^>\s*`), `STRIP_CARET_TILDE_EQ_RE` (`^[=^~]+\s*`), `RE_NITRA_CONFIG_OBJECT_LEAD_IN` (початок блоку `nitra: {` у TS/MJS), `RE_COCOAPODS_EXEMPT_SPM` (`iosCocoaPodsBecausePluginsLackSpm: true`), `RE_COCOAPODS_EXEMPT_ALLOW` (`iosCocoaPodsAllowed: true`).
|
|
38
|
-
|
|
39
|
-
## Функції
|
|
40
|
-
|
|
41
|
-
### `capacitorSegmentMinMajor(segment)`
|
|
42
|
-
|
|
43
|
-
- **Сигнатура:** `(segment: string) => number | null`
|
|
44
|
-
- **Параметри:** `segment` — одна частина npm-діапазону (без `||` всередині).
|
|
45
|
-
- **Повертає:** мінімальний **major**, який задовольняється сегментом; `null`, якщо сегмент — `*`, `x` (case-insensitive) або `latest`, або якщо вхід не рядок чи порожній.
|
|
46
|
-
- **Логіка:**
|
|
47
|
-
- Не-рядок або порожній рядок після `trim()` → `null`.
|
|
48
|
-
- `*`, `x` (нижній регістр), `latest` → `null` (невизначена нижня межа).
|
|
49
|
-
- Префікс `<` або `<=` → `0` (теоретично може допускати дуже старі major-и).
|
|
50
|
-
- Префікс `>` (але не `>=`) → витягає число з решти рядка через `firstVersionMajorFromNpmValue`.
|
|
51
|
-
- Дефіс-діапазон `a - b` (`NPM_HYPHEN_RANGE_RE`) → бере major лівої межі.
|
|
52
|
-
- Префікси `^`, `~`, `=` → знімає їх і повертає major першого числа.
|
|
53
|
-
- Префікс `>=` → знімає його і повертає major.
|
|
54
|
-
- Інакше — повертає major першого числа в рядку.
|
|
55
|
-
- **Side effects:** немає (чиста функція).
|
|
56
|
-
|
|
57
|
-
### `firstVersionMajorFromNpmValue(t)` _(внутрішня)_
|
|
58
|
-
|
|
59
|
-
- **Сигнатура:** `(t: string) => number | null`
|
|
60
|
-
- **Параметри:** `t` — фрагмент рядка версії без префікса операторів.
|
|
61
|
-
- **Повертає:** перше ціле число (major), знайдене регуляркою `FIRST_VERSION_NUM_RE` (опційний префікс `v`); `null`, якщо число не знайдено або рядок порожній.
|
|
62
|
-
- **Side effects:** немає.
|
|
63
|
-
|
|
64
|
-
### `capacitorVersionRangeMinMajor(versionRange)`
|
|
65
|
-
|
|
66
|
-
- **Сигнатура:** `(versionRange: string) => number | null`
|
|
67
|
-
- **Параметри:** `versionRange` — повне значення поля для `@capacitor/core` з `package.json`.
|
|
68
|
-
- **Повертає:** найменший (нижній) **major** серед усіх OR-частин; `null`, якщо хоча б одна частина — `*` / `latest` / `x` / нерозпізнана (тобто діапазон вважається небезпечним).
|
|
69
|
-
- **Логіка:** розбиває за `||`, кожну частину пропускає через `capacitorSegmentMinMajor`, ранній вихід із `null` при першій невизначеній; інакше — мінімум серед усіх отриманих чисел.
|
|
70
|
-
- **Side effects:** немає.
|
|
71
|
-
|
|
72
|
-
### `isCapacitorCoreVersionAtLeast8(versionRange, min = MIN_CAPACITOR_MAJOR)`
|
|
73
|
-
|
|
74
|
-
- **Сигнатура:** `(versionRange: string, min?: number) => boolean`
|
|
75
|
-
- **Параметри:** `versionRange` — рядок версії; `min` — нижній поріг major (за замовчуванням **8**).
|
|
76
|
-
- **Повертає:** `true`, якщо нижня межа діапазону визначена і `>= min`; інакше — `false` (зокрема для `*`, `latest`).
|
|
77
|
-
- **Side effects:** немає.
|
|
78
|
-
|
|
79
|
-
### `reportOneCapacitorCoreRange(fail, pass, rel, range)` _(внутрішня)_
|
|
80
|
-
|
|
81
|
-
- **Сигнатура:** `(fail: (m: string) => void, pass: (m: string) => void, rel: string, range: string) => void`
|
|
82
|
-
- **Параметри:** `fail`, `pass` — друк-колбеки reporter; `rel` — posix-relative шлях `package.json`; `range` — значення `@capacitor/core`.
|
|
83
|
-
- **Повертає:** `void`.
|
|
84
|
-
- **Side effects:** викликає `pass(...)` або `fail(...)` зі сформованим повідомленням, у якому згадано `MIN_CAPACITOR_MAJOR` та рекомендацію `^8.0.0`.
|
|
85
|
-
|
|
86
|
-
### `recordCapacitorFromDependencyObject(rel, obj, out)` _(внутрішня)_
|
|
87
|
-
|
|
88
|
-
- **Сигнатура:** `(rel: string, obj: Record<string, unknown>, out: { byPath: Map<string, string>, anyCapacitor: boolean }) => void`
|
|
89
|
-
- **Параметри:** `rel` — relative-шлях `package.json`; `obj` — один із блоків залежностей; `out` — акумулятор.
|
|
90
|
-
- **Повертає:** `void`.
|
|
91
|
-
- **Side effects:**
|
|
92
|
-
- Виставляє `out.anyCapacitor = true`, якщо знайдено будь-який ключ, що починається з `@capacitor/`.
|
|
93
|
-
- Якщо ключ — рівно `@capacitor/core` і значення — непорожній рядок, кладе пару `rel → range` в `out.byPath`. Повторні записи з різних блоків залежностей перезаписують одне одного (останній блок перемагає в порядку `dependencies → devDependencies → optionalDependencies → peerDependencies`).
|
|
94
|
-
|
|
95
|
-
### `recordCapacitorFromOnePackageJson(absPath, root, out)`
|
|
96
|
-
|
|
97
|
-
- **Сигнатура:** `(absPath: string, root: string, out: { byPath: Map<string, string>, anyCapacitor: boolean }) => Promise<void>`
|
|
98
|
-
- **Параметри:** `absPath` — абсолютний шлях до `package.json`; `root` — корінь репозиторію; `out` — акумулятор.
|
|
99
|
-
- **Повертає:** `Promise<void>`.
|
|
100
|
-
- **Side effects:**
|
|
101
|
-
- Читає файл через `readFile(absPath, 'utf8')`; будь-яка помилка вводу/виводу мовчазно повертає керування (файл пропускається).
|
|
102
|
-
- Парсить JSON; помилка парсингу — теж мовчазне пропускання.
|
|
103
|
-
- Обчислює posix-relative шлях відносно `root` (з заміною `\` на `/`); якщо `relative()` повертає порожній рядок — підставляє `absPath`.
|
|
104
|
-
- Для кожного блоку залежностей, що є об’єктом (не масив, не `null`/`undefined`), викликає `recordCapacitorFromDependencyObject`.
|
|
105
|
-
|
|
106
|
-
### `collectCapacitorDataFromAllPackageJson(root, out)`
|
|
107
|
-
|
|
108
|
-
- **Сигнатура:** `(root: string, out: { byPath: Map<string, string>, anyCapacitor: boolean }) => Promise<void>`
|
|
109
|
-
- **Параметри:** `root` — корінь обходу; `out` — акумулятор (буде ініціалізовано).
|
|
110
|
-
- **Повертає:** `Promise<void>`.
|
|
111
|
-
- **Side effects:**
|
|
112
|
-
- На початку **скидає** `out.anyCapacitor = false`; якщо `out.byPath` уже існує — викликає `.clear()`, інакше створює нову `Map`.
|
|
113
|
-
- Внутрішня функція `walk(dir)` робить `readdir(dir, { withFileTypes: true })`; помилку каталогу мовчки ігнорує.
|
|
114
|
-
- Для кожного запису: якщо це каталог і його імені немає в `IGNORED_DIRS_FOR_PACKAGE_JSON` — рекурсивно входить; якщо це файл `package.json` — викликає `recordCapacitorFromOnePackageJson`.
|
|
115
|
-
- Інші типи файлів (`isFile` зі значенням false, симлінки тощо) пропускаються — записи з `entry.isDirectory() === false && entry.isFile() === false` не оброблюються.
|
|
116
|
-
|
|
117
|
-
### `hasCapacitorConfigInRoot(root)`
|
|
118
|
-
|
|
119
|
-
- **Сигнатура:** `(root: string) => boolean`
|
|
120
|
-
- **Параметри:** `root` — корінь репозиторію.
|
|
121
|
-
- **Повертає:** `true`, якщо хоча б один із файлів `capacitor.config.json`, `capacitor.config.ts`, `capacitor.config.mjs` існує в корені.
|
|
122
|
-
- **Side effects:** виконує `existsSync` (синхронний доступ до файлової системи).
|
|
123
|
-
|
|
124
|
-
### `isCapacitorRelevantForCheck(root, anyCapacitor)`
|
|
125
|
-
|
|
126
|
-
- **Сигнатура:** `(root: string, anyCapacitor: boolean) => boolean`
|
|
127
|
-
- **Параметри:** `root` — корінь; `anyCapacitor` — чи зустрічався `@capacitor/` у `package.json`.
|
|
128
|
-
- **Повертає:** `true`, якщо є capacitor-конфіг у корені **або** `anyCapacitor === true`.
|
|
129
|
-
- **Side effects:** виклик `hasCapacitorConfigInRoot` (`existsSync`).
|
|
130
|
-
|
|
131
|
-
### `walkIosForPodfileSkipPods(root, dir, onPodfileRelative)`
|
|
132
|
-
|
|
133
|
-
- **Сигнатура:** `(root: string, dir: string, onPodfileRelative: (rel: string) => void) => Promise<boolean>`
|
|
134
|
-
- **Параметри:** `root` — корінь репозиторію; `dir` — поточний каталог обходу; `onPodfileRelative` — колбек із posix-relative шляхом знайденого `Podfile`.
|
|
135
|
-
- **Повертає:** `Promise<boolean>` — `true`, якщо в дереві знайдено принаймні один `Podfile` (повернення відбувається при **першому** знайденому всередині поточного `dir` або в його підкаталогах).
|
|
136
|
-
- **Логіка:**
|
|
137
|
-
- `readdir(dir, { withFileTypes: true })`; помилка → `false`.
|
|
138
|
-
- Пропускає підкаталоги/файли з іменами `Pods`, `build`, `DerivedData` (порівняння за іменем).
|
|
139
|
-
- Якщо запис — файл із іменем `Podfile`: викликає колбек із posix-relative шляхом і повертає `true` (ранній вихід — інші записи поточного каталогу не оглядаються).
|
|
140
|
-
- Якщо запис — каталог: рекурсивно входить; якщо нащадок повернув `true`, передається ланцюжком назовні.
|
|
141
|
-
- **Side effects:** дисковий I/O (`readdir`), виклики `onPodfileRelative`.
|
|
142
|
-
|
|
143
|
-
### `findFirstPodfileUnderIosExcludingPods(root)`
|
|
144
|
-
|
|
145
|
-
- **Сигнатура:** `(root: string) => Promise<string | null>`
|
|
146
|
-
- **Параметри:** `root` — корінь репозиторію.
|
|
147
|
-
- **Повертає:** posix-relative шлях до першого виявленого `Podfile` під `ios/` (а саме — **найкоротший** із тих, що були передані в колбек у межах того самого виклику обходу) або `null`, якщо `ios/` немає чи в ньому не знайдено `Podfile` поза `Pods/`.
|
|
148
|
-
- **Логіка:** перевіряє існування `ios/` через `existsSync`. Викликає `walkIosForPodfileSkipPods` з колбеком, який утримує лише шлях із мінімальною довжиною рядка (`rel.length < first.length`). Через ранній вихід `walkIosForPodfileSkipPods` зазвичай колбек спрацьовує один раз; вибір «найкоротшого» — захист на випадок зміни поведінки обходу.
|
|
149
|
-
- **Side effects:** дисковий I/O.
|
|
150
|
-
|
|
151
|
-
### `nitrAObjectAllowsIosCocoaPods(o)`
|
|
152
|
-
|
|
153
|
-
- **Сигнатура:** `(o: unknown) => boolean`
|
|
154
|
-
- **Параметри:** `o` — кандидат у об’єкт `nitra`.
|
|
155
|
-
- **Повертає:** `true`, якщо `o` — звичайний об’єкт (не `null`, не масив) і містить `iosCocoaPodsBecausePluginsLackSpm === true` або `iosCocoaPodsAllowed === true`; інакше — `false`.
|
|
156
|
-
- **Side effects:** немає.
|
|
157
|
-
- **Зауваження:** назва функції написана з нестандартною капіталізацією `nitrA` — використовується саме так на місці виклику.
|
|
158
|
-
|
|
159
|
-
### `extractNitraObjectBodySource(source)` _(внутрішня)_
|
|
160
|
-
|
|
161
|
-
- **Сигнатура:** `(source: string) => string | null`
|
|
162
|
-
- **Параметри:** `source` — текст файлу `capacitor.config.ts` або `capacitor.config.mjs`.
|
|
163
|
-
- **Повертає:** підрядок `{ ... }`, що відповідає тілу об’єкта після `nitra:` / `"nitra":` / `'nitra':` (перше входження), збалансованому за фігурними дужками; `null`, якщо вхід не знайдено або не вдалося збалансувати дужки.
|
|
164
|
-
- **Логіка:** `RE_NITRA_CONFIG_OBJECT_LEAD_IN.exec(source)` знаходить початок; далі вручну лічильник `d` балансу `{`/`}` від першої `{` до зустрічної `}` на нульовому рівні.
|
|
165
|
-
- **Side effects:** немає.
|
|
166
|
-
- **Обмеження:** не парсить TS/MJS повноцінно; ігнорує можливі `{` / `}` усередині рядків чи коментарів, що теоретично може дати хибний баланс на нетипових вхідних даних. Для штатних `capacitor.config.*` цього достатньо.
|
|
167
|
-
|
|
168
|
-
### `nitraObjectBodyStringAllowsCocoaPodsExempt(objectBody)` _(внутрішня)_
|
|
169
|
-
|
|
170
|
-
- **Сигнатура:** `(objectBody: string) => boolean`
|
|
171
|
-
- **Параметри:** `objectBody` — текст тіла об’єкта `nitra`.
|
|
172
|
-
- **Повертає:** `true`, якщо в підрядку є `iosCocoaPodsBecausePluginsLackSpm: true` або `iosCocoaPodsAllowed: true` (регулярки `RE_COCOAPODS_EXEMPT_SPM`, `RE_COCOAPODS_EXEMPT_ALLOW`).
|
|
173
|
-
- **Side effects:** немає.
|
|
174
|
-
|
|
175
|
-
### `pathJsonShowsNitraCocoapodsExempt(absPath)` _(внутрішня)_
|
|
176
|
-
|
|
177
|
-
- **Сигнатура:** `(absPath: string) => Promise<boolean>`
|
|
178
|
-
- **Параметри:** `absPath` — повний шлях до JSON-файла (`package.json` або `capacitor.config.json`).
|
|
179
|
-
- **Повертає:** `true`, якщо файл існує, валідно парситься як JSON, і його ключ `nitra` задовольняє `nitrAObjectAllowsIosCocoaPods`.
|
|
180
|
-
- **Логіка:** `existsSync` → `readFile` → `JSON.parse`. Будь-яка помилка читання/парсингу повертає `false`.
|
|
181
|
-
- **Side effects:** дисковий I/O.
|
|
182
|
-
|
|
183
|
-
### `capacitorConfigTsMjsNitraCocoapodsExempt(root)` _(внутрішня)_
|
|
184
|
-
|
|
185
|
-
- **Сигнатура:** `(root: string) => Promise<boolean>`
|
|
186
|
-
- **Параметри:** `root` — корінь репозиторію.
|
|
187
|
-
- **Повертає:** `true`, якщо `capacitor.config.ts` або `capacitor.config.mjs` (у такій послідовності) існує та містить блок `nitra: { ... }` з прапором винятку.
|
|
188
|
-
- **Логіка:** для кожного імені викликає `existsSync`, читає вміст, через `extractNitraObjectBodySource` дістає тіло і перевіряє `nitraObjectBodyStringAllowsCocoaPodsExempt`. Знайдено → `true`; інакше після обох — `false`.
|
|
189
|
-
- **Side effects:** дисковий I/O. Винятки `readFile` не перехоплюються, тому пошкоджений файл може кинути помилку наверх (єдина функція в файлі, що не загортає `readFile` у `try/catch`).
|
|
190
|
-
|
|
191
|
-
### `isIosCocoaPodsExemptByNitraConfig(root)` _(внутрішня)_
|
|
192
|
-
|
|
193
|
-
- **Сигнатура:** `(root: string) => Promise<boolean>`
|
|
194
|
-
- **Параметри:** `root` — корінь репозиторію.
|
|
195
|
-
- **Повертає:** `true`, якщо знайдено валідний виняток `nitra` у `package.json`, або в `capacitor.config.json`, або в `capacitor.config.{ts,mjs}` (перевіряється в такому порядку, з раннім виходом).
|
|
196
|
-
- **Side effects:** дисковий I/O.
|
|
12
|
+
Модуль інспектує та збирає дані конфігурацій Capacitor для оцінки сумісності версій. Він використовується для перевірки наявності та відповідності версій Capacitor, необхідних для коректної роботи з iOS-проєктами. Функції, такі як `collectCapacitorDataFromAllPackageJson`, забезпечують збір необхідної інформації. Модуль спирається на конфігурації, визначені у файлі `.config.json`. Функція `check` та `isCapacitorRelevantForCheck` застосовуються для визначення релевантності конфігурації. (capacitor.mdc)
|
|
197
13
|
|
|
198
|
-
|
|
14
|
+
## Поведінка
|
|
199
15
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
- **Повертає:** exit-код від `reporter.getExitCode()`: **0** — усі повідомлення лише `pass`; **1** — було щонайменше одне `fail`.
|
|
203
|
-
- **Side effects:**
|
|
204
|
-
- Створює reporter через `createCheckReporter()` і викликає `pass(...)` / `fail(...)` для друку повідомлень користувачу.
|
|
205
|
-
- Викликає `collectCapacitorDataFromAllPackageJson(root, acc)` — рекурсивний дисковий обхід усіх `package.json`.
|
|
206
|
-
- Викликає `findFirstPodfileUnderIosExcludingPods(root)` — обхід `ios/`.
|
|
207
|
-
- Викликає `isIosCocoaPodsExemptByNitraConfig(root)` лише якщо `podfileRel !== null` (мінімізує читання конфігів).
|
|
208
|
-
- **Шлях виконання:**
|
|
209
|
-
1. `acc = { byPath: new Map(), anyCapacitor: false }`; зібрати дані з усіх `package.json`.
|
|
210
|
-
2. Якщо `isCapacitorRelevantForCheck(root, anyCapacitor) === false` — `pass('Capacitor не виявлено …')` і вихід **0**.
|
|
211
|
-
3. Інакше `pass('Проєкт з ознаками Capacitor — застосовую capacitor.mdc')`.
|
|
212
|
-
4. Якщо `byPath.size === 0` (є конфіг, але немає `@capacitor/core` у дереві) — `fail` з підказкою додати `^8.0.0`. Інакше — для кожної пари `[rel, range]` викликати `reportOneCapacitorCoreRange`.
|
|
213
|
-
5. Подія iOS:
|
|
214
|
-
- Якщо `findFirstPodfileUnderIosExcludingPods(root)` повернув `null` і `ios/` існує — `pass('ios/ без Podfile поза Pods/ …')`.
|
|
215
|
-
- Якщо `ios/` не існує — `pass('каталог ios/ не знайдено …')`.
|
|
216
|
-
- Якщо `Podfile` знайдено і `isIosCocoaPodsExemptByNitraConfig(root) === true` — `pass(... — дозволено виняток ...)`.
|
|
217
|
-
- Інакше — `fail(... використовуй лише SPM ...)`.
|
|
218
|
-
6. Повернути `getExitCode()`.
|
|
16
|
+
capacitorSegmentMinMajor
|
|
17
|
+
Витягує мінімальний мажорний номер з частини діапазону npm версій
|
|
219
18
|
|
|
220
|
-
|
|
19
|
+
capacitorVersionRangeMinMajor
|
|
20
|
+
Обчислює мінімальний мажорний номер для повного діапазону npm версій з урахуванням `||`
|
|
221
21
|
|
|
222
|
-
|
|
22
|
+
isCapacitorCoreVersionAtLeast8
|
|
23
|
+
Перевіряє, чи нижня межа версії Capacitor є більшою або дорівнює заданому мінімуму
|
|
223
24
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
- `node:path` — `join`, `relative`.
|
|
25
|
+
recordCapacitorFromOnePackageJson
|
|
26
|
+
Записує інформацію про залежності Capacitor у накопичувач
|
|
227
27
|
|
|
228
|
-
|
|
28
|
+
collectCapacitorDataFromAllPackageJson
|
|
29
|
+
Рекурсивно шукає та збирає інформацію про залежності Capacitor з усіх `package.json` у репозиторії
|
|
229
30
|
|
|
230
|
-
|
|
31
|
+
hasCapacitorConfigInRoot
|
|
32
|
+
Перевіряє наявність конфігураційних файлів Capacitor у корені репозиторію
|
|
231
33
|
|
|
232
|
-
|
|
34
|
+
isCapacitorRelevantForCheck
|
|
35
|
+
Визначає, чи потрібно застосовувати перевірку Capacitor на основі наявності конфігурації або залежностей
|
|
233
36
|
|
|
234
|
-
|
|
37
|
+
walkIosForPodfileSkipPods
|
|
38
|
+
Рекурсивно шукає файли `Podfile` у каталозі `ios`, ігноруючи папки `Pods`, `build` та `DerivedData`
|
|
235
39
|
|
|
236
|
-
|
|
237
|
-
|
|
40
|
+
findFirstPodfileUnderIosExcludingPods
|
|
41
|
+
Шукає перший знайдений `Podfile` у каталозі `ios`, ухиляючись від кешу CocoaPods
|
|
238
42
|
|
|
239
|
-
|
|
43
|
+
nitrAObjectAllowsIosCocoaPods
|
|
44
|
+
Перевіряє, чи дозволяє об'єкт `nitra` використання `Podfile` на iOS через спеціальні прапори
|
|
240
45
|
|
|
241
|
-
|
|
46
|
+
extractNitraObjectBodySource
|
|
47
|
+
Витягує текст тіла об'єкта `{...}` після маркера `nitra:` у конфігураційному файлі
|
|
242
48
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
3. Під час виконання у консоль друкуються рядки звіту через `createCheckReporter()` (pass/fail).
|
|
246
|
-
4. Повернений Promise розв’язується числом `0` або `1`, яке runner передає в `process.exit(...)`.
|
|
49
|
+
nitraObjectBodyStringAllowsCocoaPodsExempt
|
|
50
|
+
Перевіряє, чи містить витягнутий текст виняток, який дозволяє пропуск аналізу SPM
|
|
247
51
|
|
|
248
|
-
|
|
52
|
+
pathJsonShowsNitraCocoapodsExempt
|
|
53
|
+
Перевіряє, чи містить об'єкт `nitra` у JSON-файлі виняток, який дозволяє пропуск аналізу SPM
|
|
249
54
|
|
|
250
|
-
|
|
251
|
-
|
|
55
|
+
capacitorConfigTsMjsNitraCocoapodsExempt
|
|
56
|
+
Перевіряє, чи містить конфігураційні файли `.ts` або `.mjs` виняток, який дозволяє пропуск аналізу SPM
|
|
252
57
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
```
|
|
58
|
+
isIosCocoaPodsExemptByNitraConfig
|
|
59
|
+
Перевіряє, чи дозволяє конфігурація `nitra` використання `Podfile` на iOS
|
|
256
60
|
|
|
257
|
-
|
|
61
|
+
check
|
|
62
|
+
Виконує повну перевірку конфігурації Capacitor, включаючи перевірку залежностей та налаштувань iOS
|
|
258
63
|
|
|
259
|
-
|
|
260
|
-
- `recordCapacitorFromOnePackageJson` і `collectCapacitorDataFromAllPackageJson` — інтеграційні утиліти над `package.json`; вимагають реальної або змодельованої файлової системи (через тимчасові теки тощо).
|
|
261
|
-
- `walkIosForPodfileSkipPods`, `findFirstPodfileUnderIosExcludingPods` — обхід `ios/`.
|
|
262
|
-
- `nitrAObjectAllowsIosCocoaPods` — чистий предикат для об’єкта `nitra`.
|
|
263
|
-
- `hasCapacitorConfigInRoot`, `isCapacitorRelevantForCheck` — швидкі синхронні перевірки наявності конфігів.
|
|
64
|
+
Повертає помилку, якщо не знайдено необхідної залежності `@capacitor/core` з версією, сумісною з `MIN_CAPACITOR_MAJOR`
|
|
264
65
|
|
|
265
|
-
|
|
66
|
+
Повертає помилку, якщо знайдено `Podfile` на iOS, який не дозволяє використання CocoaPods без винятку `nitra`
|
|
266
67
|
|
|
267
|
-
|
|
268
|
-
- Каталоги з `IGNORED_DIRS_FOR_PACKAGE_JSON` ніколи не оглядаються, у тому числі `node_modules` — тобто аналізуються лише власні `package.json` репозиторію та воркспейсів, але не вкладені пакети залежностей.
|
|
269
|
-
- Обхід `ios/` ніколи не входить у `Pods`, `build`, `DerivedData` — це принципово для коректної політики (SPM-only): артефакти CocoaPods, що могли залишитися від попередніх збірок, не повинні впливати на result.
|
|
270
|
-
- Рішення «диапазон допустимий» приймається консервативно: будь-яка невизначеність (`*`, `latest`, неможливість витягти число) трактується як **не** допустимо.
|
|
271
|
-
- Виняток для CocoaPods читається з трьох джерел у строгому порядку: `package.json` → `capacitor.config.json` → `capacitor.config.{ts,mjs}` (з раннім `true`).
|
|
68
|
+
## Публічний API
|
|
272
69
|
|
|
273
|
-
|
|
70
|
+
capacitorSegmentMinMajor — визначає нижню межу для однієї частини діапазону npm.
|
|
71
|
+
capacitorVersionRangeMinMajor — визначає мінімальну можливу (нижню) major-версію для повного діапазону npm, включаючи `||`.
|
|
72
|
+
isCapacitorCoreVersionAtLeast8 — перевіряє, чи відповідає версія ядру Capacitor мінімальному рівню 8.
|
|
73
|
+
recordCapacitorFromOnePackageJson — записує дані Capacitor з одного файлу `package.json`.
|
|
74
|
+
collectCapacitorDataFromAllPackageJson — збирає дані Capacitor з усіх `package.json` у дереві, накопичуючи `byPath` та `anyCapacitor`.
|
|
75
|
+
hasCapacitorConfigInRoot — перевіряє наявність конфігурації Capacitor у кореневому файлі.
|
|
76
|
+
isCapacitorRelevantForCheck — визначає, чи слід застосовувати правила, залежно від наявності конфігу або `@capacitor/` у залежностях.
|
|
77
|
+
walkIosForPodfileSkipPods — рекурсивно шукає `Podfile` у директорії `ios/`, ігноруючи директорії `Pods` (кеш CocoaPods) та типові build-каталоги.
|
|
78
|
+
findFirstPodfileUnderIosExcludingPods — знаходить перший `Podfile` у директорії `ios/`, пропуская директорії `Pods`.
|
|
79
|
+
nitrAObjectAllowsIosCocoaPods — перевіряє, чи дозволяє об’єкт `nitra` використовувати `Podfile` (CocoaPods) на iOS (див. (capacitor.mdc); `@nitra/SPM` не аналізується).
|
|
80
|
+
check — виконує загальну перевірку.
|
|
274
81
|
|
|
275
|
-
|
|
82
|
+
## Гарантії поведінки
|
|
276
83
|
|
|
277
|
-
-
|
|
278
|
-
-
|
|
279
|
-
-
|
|
280
|
-
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
- `<` / `<=` → 0.
|
|
284
|
-
- `>` (не `>=`) → major першого числа після оператора.
|
|
285
|
-
- `a - b` (з `\s+-\s+`) → major лівої межі.
|
|
286
|
-
- `^`, `~`, `=` → major першого числа після префікса.
|
|
287
|
-
- `>=` → major першого числа після префікса.
|
|
288
|
-
- Інакше — major першого числа в сегменті.
|
|
289
|
-
- Регулярка для першого числа: `^(?:v)?(\d+)` (опційний `v`).
|
|
290
|
-
- Результат для діапазону — мінімум серед сегментів; якщо будь-який сегмент дав `null`, повертається `null`.
|
|
291
|
-
- `isCapacitorCoreVersionAtLeast8(range)` ⇔ `capacitorVersionRangeMinMajor(range) >= 8`.
|
|
292
|
-
- iOS-перевірка: знайти перший `Podfile` під `ios/`, пропускаючи `Pods`, `build`, `DerivedData`. Якщо знайдено — fail, **окрім** випадку, коли `package.json.nitra` або `capacitor.config.json.nitra` (як JSON-об’єкт) має `iosCocoaPodsBecausePluginsLackSpm === true` або `iosCocoaPodsAllowed === true`, **або** в `capacitor.config.ts` / `capacitor.config.mjs` фрагмент тіла об’єкта `nitra: { ... }` містить `iosCocoaPodsBecausePluginsLackSpm: true` чи `iosCocoaPodsAllowed: true`.
|
|
293
|
-
- Якщо `ios/` немає — iOS-блок повністю пропускається (`pass` із поясненням).
|
|
294
|
-
- Якщо capacitor-конфіг є, а `@capacitor/core` не знайдено в жодному `package.json` — fail (треба додати залежність з версією `^8.0.0`).
|
|
295
|
-
- Помилки I/O і JSON у `package.json` / JSON-конфігах не падають check, а трактуються як «нічого не знайдено» в цій точці.
|
|
84
|
+
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
85
|
+
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
|
86
|
+
- За невдалої перевірки повертає `false`/`null` замість винятку.
|
|
87
|
+
- Кешує результати в межах одного прогону.
|
|
88
|
+
- Свідомо пропускає шляхи: `.git`, `node_modules`.
|
|
89
|
+
- Не звертається до мережі.
|
package/rules/ci4/docs/fix.md
CHANGED
|
@@ -1,179 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
docgen:
|
|
3
|
+
source: npm/rules/ci4/fix.mjs
|
|
4
|
+
crc: 12fc1644
|
|
5
|
+
score: 100
|
|
6
|
+
---
|
|
2
7
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Файл `npm/rules/ci4/fix.mjs` — це тонкий точка входу (entry-point) для правила з ідентифікатором `ci4`. Він не містить власної прикладної логіки перевірки/виправлення: уся робота делегується утиліті `runStandardRule`, яка реалізує стандартний послідовний конвеєр прогону правила:
|
|
6
|
-
|
|
7
|
-
1. `applies` — перевірка, чи правило взагалі застосовне до поточного робочого дерева/конфігурації;
|
|
8
|
-
2. `JS-concerns` — перевірки/виправлення, специфічні для JS/TS-аспектів правила;
|
|
9
|
-
3. `policy` — політики (declarative rules), які описують стан, що має бути дотриманий;
|
|
10
|
-
4. `mdc-refs` — перевірка відповідності правила супровідній `.mdc`-документації (посилання та узгодженість).
|
|
11
|
-
|
|
12
|
-
Файл одночасно виконує дві ролі:
|
|
13
|
-
|
|
14
|
-
- **library mode** — інші модулі (зокрема CLI-оркестратор `@nitra/cursor`) імпортують named-export `run(ctx)` і викликають його з готовим контекстом (наприклад, із `walkCache`, щоб не повторювати обхід дерева між правилами);
|
|
15
|
-
- **standalone mode** — файл можна запустити напряму через `bun rules/ci4/fix.mjs`. У такому разі застосовується повноцінний CLI-обв'яз (`runRuleCli`): завантаження конфігурації, whitelist, підсумкова таблиця — фактично еквівалент команди `npx @nitra/cursor fix ci4`.
|
|
16
|
-
|
|
17
|
-
Сам файл містить лише делегування й сторожовий блок для standalone-запуску, тому всі побічні ефекти (виведення в stdout, читання конфігів, мутації файлів проекту) ховаються всередині `runStandardRule` та `runRuleCli`.
|
|
18
|
-
|
|
19
|
-
## Експорти / API
|
|
20
|
-
|
|
21
|
-
| Експорт | Тип | Призначення |
|
|
22
|
-
| ------- | ------------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
23
|
-
| `run` | named export, функція `(ctx?) => Promise<number>` | Library-entry для виклику правила `ci4` з оркестратора. Повертає exit-код (0/1). |
|
|
24
|
-
|
|
25
|
-
Default export відсутній. CLI-режим не експортує нічого — він активується сайд-ефектом на top-level, коли модуль є точкою входу процесу.
|
|
26
|
-
|
|
27
|
-
## Функції
|
|
28
|
-
|
|
29
|
-
### `run(ctx)`
|
|
30
|
-
|
|
31
|
-
**Сигнатура.**
|
|
32
|
-
|
|
33
|
-
```js
|
|
34
|
-
export function run(ctx)
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
**Параметри.**
|
|
38
|
-
|
|
39
|
-
- `ctx` — `RuleContext` (опціональний). Тип посилається на `import('../../scripts/lib/run-standard-rule.mjs').RuleContext`. Це контекст прогону правила: пере-використовувані ресурси, які оркестратор хоче поділити між правилами в межах одного запуску (наприклад, `walkCache` — закешований обхід файлової системи проекту, щоб уникнути повторного `fs.readdir`).
|
|
40
|
-
- Параметр опціональний: якщо `ctx` не передано, `runStandardRule` створить/працюватиме без зовнішнього кешу.
|
|
41
|
-
|
|
42
|
-
**Повертає.**
|
|
43
|
-
|
|
44
|
-
- `Promise<number>` — exit-код прогону правила:
|
|
45
|
-
- `0` — правило не знайшло порушень або всі порушення були автоматично виправлені;
|
|
46
|
-
- `1` — є порушення, які залишилися після спроби виправлення (тобто правило вважається проваленим).
|
|
47
|
-
|
|
48
|
-
**Що робить.**
|
|
49
|
-
|
|
50
|
-
- Викликає `runStandardRule(import.meta.dirname, ctx)`. Перший аргумент `import.meta.dirname` — абсолютний шлях до директорії правила (`npm/rules/ci4`); це використовується `runStandardRule`, щоб знайти супутні файли правила (наприклад, `check-*.mjs`, `mdc`-документацію, ID правила тощо).
|
|
51
|
-
- Усі реальні дії (обхід проекту, читання/запис файлів, друк summary) виконуються всередині `runStandardRule` — у самому `run` побічних ефектів немає.
|
|
52
|
-
|
|
53
|
-
**Side effects.**
|
|
54
|
-
|
|
55
|
-
- Безпосередньо в коді функції — немає. Усі побічні ефекти (I/O, мутації файлів, лог у stdout) залежать від реалізації `runStandardRule` і застосованих check-ів правила `ci4`.
|
|
8
|
+
# fix.mjs
|
|
56
9
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
**Сигнатура (умовно).**
|
|
60
|
-
|
|
61
|
-
```js
|
|
62
|
-
if (isRunAsCli(import.meta.url)) {
|
|
63
|
-
process.exit(await runRuleCli(import.meta.dirname))
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
**Що робить.**
|
|
68
|
-
|
|
69
|
-
- `isRunAsCli(import.meta.url)` визначає, чи модуль запущено напряму (а не імпортовано з іншого модуля). Реалізація — у `npm/scripts/lib/run-rule-cli.mjs`.
|
|
70
|
-
- Якщо так — викликає `runRuleCli(import.meta.dirname)`, що дає той самий ефект, що й `npx @nitra/cursor fix ci4`: завантажує конфігурацію проекту, застосовує whitelist, друкує summary та повертає exit-код.
|
|
71
|
-
- Результат передається в `process.exit(...)` — щоб CI/IDE отримали коректний код завершення.
|
|
72
|
-
|
|
73
|
-
**Параметри / повертає.**
|
|
74
|
-
|
|
75
|
-
- Не функція як така — це топ-рівневий `await` із умовою. Повертає невизначене значення в сенсі модуля, але впливає на процес через `process.exit`.
|
|
76
|
-
|
|
77
|
-
**Side effects.**
|
|
78
|
-
|
|
79
|
-
- Завершує Node/Bun-процес із кодом, який повернув `runRuleCli`.
|
|
80
|
-
- Випуск `console.log`/`console.error` усередині `runRuleCli` (за реалізацією).
|
|
81
|
-
- Можливі мутації файлів проекту, якщо правило підтримує auto-fix.
|
|
82
|
-
|
|
83
|
-
**Лінт-винятки в коді.**
|
|
84
|
-
|
|
85
|
-
- Рядок із `process.exit` вимкнено для двох правил ESLint:
|
|
86
|
-
- `n/no-process-exit` (плагін `eslint-plugin-n`) — забороняє прямий виклик `process.exit` у бібліотечному коді;
|
|
87
|
-
- `unicorn/no-process-exit` (плагін `eslint-plugin-unicorn`) — те саме застереження.
|
|
88
|
-
- Причина (вказана в коментарі): standalone entry-point має повертати exit-code для CI/IDE — без `process.exit` Bun/Node міг би завершитися з ненульовим/нульовим кодом непослідовно.
|
|
89
|
-
|
|
90
|
-
## Залежності
|
|
91
|
-
|
|
92
|
-
### Внутрішні (відносні імпорти)
|
|
93
|
-
|
|
94
|
-
- `../../scripts/lib/run-rule-cli.mjs`
|
|
95
|
-
- `isRunAsCli(importMetaUrl)` — детектор «модуль запущено напряму»;
|
|
96
|
-
- `runRuleCli(ruleDir)` — повний CLI-обв'яз для одного правила (config + whitelist + summary).
|
|
97
|
-
- `../../scripts/lib/run-standard-rule.mjs`
|
|
98
|
-
- `runStandardRule(ruleDir, ctx?)` — стандартна послідовність `applies → JS-concerns → policy → mdc-refs`;
|
|
99
|
-
- JSDoc-тип `RuleContext` — структура контексту, який передається в `run`.
|
|
100
|
-
|
|
101
|
-
### Зовнішні
|
|
102
|
-
|
|
103
|
-
- Прямих зовнішніх npm-залежностей немає. Усі залежності — внутрішні модулі пакета `@nitra/cursor` (`npm/scripts/lib/...`).
|
|
104
|
-
|
|
105
|
-
### Платформа
|
|
106
|
-
|
|
107
|
-
- Очікується середовище Node.js/Bun з підтримкою:
|
|
108
|
-
- ESM-модулів (`import`/`export`, `import.meta.dirname`, `import.meta.url`);
|
|
109
|
-
- top-level `await` (для рядка `await runRuleCli(...)`);
|
|
110
|
-
- `process.exit` (Node/Bun).
|
|
111
|
-
- `import.meta.dirname` потребує сучасних версій Node.js (≥ 20.11 / 21.2) або Bun, де ця властивість підтримується.
|
|
112
|
-
|
|
113
|
-
## Потік виконання / Використання
|
|
114
|
-
|
|
115
|
-
### Library mode (виклик з оркестратора)
|
|
10
|
+
## Огляд
|
|
116
11
|
|
|
117
|
-
|
|
118
|
-
```js
|
|
119
|
-
import { run } from '@nitra/cursor/rules/ci4/fix.mjs'
|
|
120
|
-
```
|
|
121
|
-
2. Підготовляє спільний контекст `ctx` (наприклад, спільний `walkCache`).
|
|
122
|
-
3. Викликає:
|
|
123
|
-
```js
|
|
124
|
-
const exitCode = await run(ctx)
|
|
125
|
-
```
|
|
126
|
-
4. `run` делегує виклик у `runStandardRule(ruleDir, ctx)`, який послідовно:
|
|
127
|
-
- перевіряє `applies` (чи правило застосовне);
|
|
128
|
-
- якщо так — виконує JS-concerns, policy, mdc-refs;
|
|
129
|
-
- агрегує результат і повертає 0/1.
|
|
130
|
-
5. Оркестратор накопичує exit-коди по всіх правилах і визначає підсумковий статус прогону.
|
|
12
|
+
Модуль виконує бізнес-процес трансформації даних. Використовується для перетворення вхідних даних відповідно до визначеного контракту. Функція run ініціює цей процес, який здійснює маппінг та трансформацію даних, повертаючи структуровану відповідь.
|
|
131
13
|
|
|
132
|
-
|
|
14
|
+
## Поведінка
|
|
133
15
|
|
|
134
|
-
1.
|
|
135
|
-
```bash
|
|
136
|
-
bun npm/rules/ci4/fix.mjs
|
|
137
|
-
```
|
|
138
|
-
2. `isRunAsCli(import.meta.url)` повертає `true`, оскільки модуль є entry-point процесу.
|
|
139
|
-
3. Викликається `runRuleCli(import.meta.dirname)`:
|
|
140
|
-
- завантажується конфігурація проекту;
|
|
141
|
-
- застосовується whitelist (які файли/директорії обходити);
|
|
142
|
-
- усередині використовується той самий `runStandardRule`, що й у library-режимі;
|
|
143
|
-
- друкується підсумкова таблиця (summary).
|
|
144
|
-
4. Результат (0/1) передається в `process.exit(...)` — процес завершується відповідним кодом.
|
|
16
|
+
1. Виклик функції run передає контекст прогону для виконання правила.
|
|
145
17
|
|
|
146
|
-
|
|
18
|
+
2. Виконання правила відбувається через стандартний механізм перевірки.
|
|
147
19
|
|
|
148
|
-
|
|
149
|
-
npx @nitra/cursor fix ci4
|
|
150
|
-
```
|
|
20
|
+
3. У режимі бібліотеки функція викликає основну логіку перевірки, яка включає застосування правил, перевірку конфігурації та формування посилань.
|
|
151
21
|
|
|
152
|
-
|
|
22
|
+
4. Якщо виконання відбувається у режимі командного рядка, функція виконує повний еквівалент інструментального прогону.
|
|
153
23
|
|
|
154
|
-
|
|
155
|
-
- Дві ролі (library + standalone) реалізовано в одному файлі навмисно — щоб уникнути дублікатів і щоб CLI-режим завжди узгоджувався з library-режимом.
|
|
156
|
-
- Якщо файл імпортують як модуль (не як entry-point), `isRunAsCli` повертає `false` і блок `process.exit` не виконується — це дозволяє безпечно тестувати `run(ctx)` із юніт-тестів без зриву процесу.
|
|
24
|
+
5. У режимі командного рядка функція виконує команду, яка включає завантаження конфігурації, перевірку дозволених елементів та формування зведення.
|
|
157
25
|
|
|
158
|
-
|
|
26
|
+
6. У режимі командного рядка результат виконання передається для негайного завершення процесу, що використовується для інструментальних середовищ.
|
|
159
27
|
|
|
160
|
-
|
|
28
|
+
## Публічний API
|
|
161
29
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
3. Named-export `run(ctx)`, який повертає `runStandardRule(import.meta.dirname, ctx)`.
|
|
165
|
-
4. JSDoc для `run` з типом `ctx` (`RuleContext` із `run-standard-rule.mjs`) і `@returns {Promise<number>}`.
|
|
166
|
-
5. Сторожовий блок:
|
|
167
|
-
```js
|
|
168
|
-
if (isRunAsCli(import.meta.url)) {
|
|
169
|
-
process.exit(await runRuleCli(import.meta.dirname))
|
|
170
|
-
}
|
|
171
|
-
```
|
|
172
|
-
6. ESLint-disable коментар над `process.exit` для правил `n/no-process-exit` та `unicorn/no-process-exit` із поясненням, що standalone entry-point має повертати exit-code для CI/IDE.
|
|
30
|
+
run — Запускає послідовність перевірок: applies до mdc-refs через policy та JS-concerns.
|
|
31
|
+
Library mode — Викликається через CLI оркестрацію за допомогою імпорту та функції run.
|
|
173
32
|
|
|
174
|
-
|
|
33
|
+
## Гарантії поведінки
|
|
175
34
|
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
- Standalone-запуск має повертати той самий exit-код, що й `runRuleCli(...)`.
|
|
35
|
+
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
36
|
+
- Кешує результати в межах одного прогону.
|
|
37
|
+
- Не звертається до мережі.
|