@nitra/cursor 1.9.20 → 1.9.23

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.
Files changed (193) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/bin/n-cursor.js +55 -49
  3. package/package.json +10 -5
  4. package/rules/abie/auto.md +1 -0
  5. package/{scripts/check-abie.mjs → rules/abie/js/check.mjs} +5 -5
  6. package/{scripts/check-adr.mjs → rules/adr/js/check.mjs} +1 -1
  7. package/rules/bun/auto.md +1 -0
  8. package/{scripts/check-bun.mjs → rules/bun/js/check.mjs} +1 -1
  9. package/rules/capacitor/auto.md +1 -0
  10. package/{scripts/check-capacitor.mjs → rules/capacitor/js/check.mjs} +1 -1
  11. package/rules/changelog/auto.md +1 -0
  12. package/{scripts/check-changelog.mjs → rules/changelog/js/check.mjs} +2 -2
  13. package/rules/docker/auto.md +1 -0
  14. package/{scripts/check-docker.mjs → rules/docker/js/check.mjs} +5 -5
  15. package/{scripts/run-docker.mjs → rules/docker/js/run.mjs} +5 -5
  16. package/rules/ga/auto.md +1 -0
  17. package/{scripts/check-ga.mjs → rules/ga/js/check.mjs} +4 -4
  18. package/{scripts/lint-ga.mjs → rules/ga/js/lint.mjs} +2 -2
  19. package/rules/graphql/auto.md +1 -0
  20. package/{scripts/check-graphql.mjs → rules/graphql/js/check.mjs} +5 -5
  21. package/rules/hasura/auto.md +1 -0
  22. package/{scripts/check-hasura.mjs → rules/hasura/js/check.mjs} +4 -4
  23. package/rules/image-avif/auto.md +1 -0
  24. package/{scripts/check-image-avif.mjs → rules/image-avif/js/check.mjs} +5 -5
  25. package/rules/image-compress/auto.md +1 -0
  26. package/{scripts/check-image-compress.mjs → rules/image-compress/js/check.mjs} +1 -1
  27. package/rules/js-bun-db/auto.md +1 -0
  28. package/{scripts/check-js-bun-db.mjs → rules/js-bun-db/js/check.mjs} +5 -5
  29. package/rules/js-bun-redis/auto.md +1 -0
  30. package/{scripts/check-js-bun-redis.mjs → rules/js-bun-redis/js/check.mjs} +4 -4
  31. package/rules/js-lint/auto.md +1 -0
  32. package/{scripts/check-js-lint.mjs → rules/js-lint/js/check.mjs} +1 -1
  33. package/rules/js-mssql/auto.md +1 -0
  34. package/{scripts/check-js-mssql.mjs → rules/js-mssql/js/check.mjs} +5 -5
  35. package/rules/js-run/auto.md +1 -0
  36. package/{scripts/check-js-run.mjs → rules/js-run/js/check.mjs} +11 -11
  37. package/rules/k8s/auto.md +1 -0
  38. package/{scripts/check-k8s.mjs → rules/k8s/js/check.mjs} +4 -4
  39. package/{scripts/run-k8s.mjs → rules/k8s/js/run.mjs} +4 -4
  40. package/rules/nginx-default-tpl/auto.md +1 -0
  41. package/{scripts/check-nginx-default-tpl.mjs → rules/nginx-default-tpl/js/check.mjs} +7 -7
  42. package/rules/npm-module/auto.md +1 -0
  43. package/{scripts/check-npm-module.mjs → rules/npm-module/js/check.mjs} +4 -4
  44. package/rules/php/auto.md +1 -0
  45. package/{scripts/check-php.mjs → rules/php/js/check.mjs} +1 -1
  46. package/{scripts/run-php.mjs → rules/php/js/run.mjs} +3 -3
  47. package/rules/rego/auto.md +1 -0
  48. package/{scripts/check-rego.mjs → rules/rego/js/check.mjs} +4 -4
  49. package/{scripts/lint-rego.mjs → rules/rego/js/lint.mjs} +1 -1
  50. package/rules/style-lint/auto.md +1 -0
  51. package/{scripts/check-style-lint.mjs → rules/style-lint/js/check.mjs} +1 -1
  52. package/rules/tauri/auto.md +1 -0
  53. package/{scripts/check-tauri.mjs → rules/tauri/js/check.mjs} +2 -2
  54. package/rules/text/auto.md +1 -0
  55. package/{scripts/check-text.mjs → rules/text/js/check.mjs} +2 -2
  56. package/{scripts/run-shellcheck-text.mjs → rules/text/js/run-shellcheck.mjs} +2 -2
  57. package/{scripts → rules/text/js}/run-v8r.mjs +2 -2
  58. package/{mdc → rules/text}/text.mdc +4 -0
  59. package/rules/vue/auto.md +1 -0
  60. package/{scripts/check-vue.mjs → rules/vue/js/check.mjs} +5 -5
  61. package/scripts/auto-rules.mjs +5 -5
  62. package/scripts/auto-skills.mjs +6 -6
  63. package/scripts/lint-conftest.mjs +13 -13
  64. package/scripts/utils/run-conftest-batch.mjs +9 -4
  65. package/skills/abie-clean/SKILL.md +59 -1
  66. package/skills/abie-clean/auto.md +1 -0
  67. package/skills/abie-kustomize/auto.md +1 -0
  68. package/skills/fix/auto.md +1 -0
  69. package/skills/lint/auto.md +1 -0
  70. package/skills/llm-patch/auto.md +1 -0
  71. package/skills/publish-telegram/auto.md +1 -0
  72. package/skills/taze/auto.md +1 -0
  73. package/bin/auto-rules.md +0 -59
  74. package/bin/auto-skills.md +0 -25
  75. /package/{mdc → rules/abie}/abie.mdc +0 -0
  76. /package/{policy/abie → rules/abie/policy}/base_deployment_preem/base_deployment_preem.rego +0 -0
  77. /package/{policy/abie → rules/abie/policy}/base_deployment_preem/base_deployment_preem_test.rego +0 -0
  78. /package/{policy/abie → rules/abie/policy}/clean_merged_ignore_branches/clean_merged_ignore_branches.rego +0 -0
  79. /package/{policy/abie → rules/abie/policy}/clean_merged_ignore_branches/clean_merged_ignore_branches_test.rego +0 -0
  80. /package/{policy/abie → rules/abie/policy}/health_check_policy/health_check_policy.rego +0 -0
  81. /package/{policy/abie → rules/abie/policy}/health_check_policy/health_check_policy_test.rego +0 -0
  82. /package/{policy/abie → rules/abie/policy}/http_route_base/http_route_base.rego +0 -0
  83. /package/{policy/abie → rules/abie/policy}/http_route_base/http_route_base_test.rego +0 -0
  84. /package/{mdc → rules/adr}/adr.mdc +0 -0
  85. /package/{policy/adr → rules/adr/policy}/settings_json/settings_json.rego +0 -0
  86. /package/{policy/adr → rules/adr/policy}/settings_local_json/settings_local_json.rego +0 -0
  87. /package/{mdc → rules/bun}/bun.mdc +0 -0
  88. /package/{policy/bun → rules/bun/policy}/bunfig/bunfig.rego +0 -0
  89. /package/{policy/bun → rules/bun/policy}/package_json/package_json.rego +0 -0
  90. /package/{policy/bun → rules/bun/policy}/package_json/package_json_test.rego +0 -0
  91. /package/{mdc → rules/capacitor}/capacitor.mdc +0 -0
  92. /package/{policy/capacitor → rules/capacitor/policy}/package_json/package_json.rego +0 -0
  93. /package/{mdc → rules/changelog}/changelog.mdc +0 -0
  94. /package/{mdc → rules/ci4}/ci4.mdc +0 -0
  95. /package/{mdc → rules/docker}/docker.mdc +0 -0
  96. /package/{policy/docker → rules/docker/policy}/lint_docker_yml/lint_docker_yml.rego +0 -0
  97. /package/{policy/docker → rules/docker/policy}/lint_docker_yml/lint_docker_yml_test.rego +0 -0
  98. /package/{policy/docker → rules/docker/policy}/package_json/package_json.rego +0 -0
  99. /package/{policy/docker → rules/docker/policy}/package_json/package_json_test.rego +0 -0
  100. /package/{mdc → rules/ga}/ga.mdc +0 -0
  101. /package/{policy/ga → rules/ga/policy}/clean_ga_workflows/clean_ga_workflows.rego +0 -0
  102. /package/{policy/ga → rules/ga/policy}/clean_merged_branch/clean_merged_branch.rego +0 -0
  103. /package/{policy/ga → rules/ga/policy}/git_ai/git_ai.rego +0 -0
  104. /package/{policy/ga → rules/ga/policy}/lint_ga/lint_ga.rego +0 -0
  105. /package/{policy/ga → rules/ga/policy}/workflow_common/workflow_common.rego +0 -0
  106. /package/{mdc → rules/graphql}/graphql.mdc +0 -0
  107. /package/{policy/graphql → rules/graphql/policy}/vscode_extensions/vscode_extensions.rego +0 -0
  108. /package/{policy/graphql → rules/graphql/policy}/vscode_extensions/vscode_extensions_test.rego +0 -0
  109. /package/{mdc → rules/hasura}/hasura.mdc +0 -0
  110. /package/{policy/hasura → rules/hasura/policy}/svc_hl/svc_hl.rego +0 -0
  111. /package/{mdc → rules/image-avif}/image-avif.mdc +0 -0
  112. /package/{policy/image_avif → rules/image-avif/policy}/package_json/package_json.rego +0 -0
  113. /package/{policy/image_avif → rules/image-avif/policy}/package_json/package_json_test.rego +0 -0
  114. /package/{mdc → rules/image-compress}/image-compress.mdc +0 -0
  115. /package/{policy/image_compress → rules/image-compress/policy}/package_json/package_json.rego +0 -0
  116. /package/{mdc → rules/js-bun-db}/js-bun-db.mdc +0 -0
  117. /package/{policy/js_bun_db → rules/js-bun-db/policy}/package_json/package_json.rego +0 -0
  118. /package/{mdc → rules/js-bun-redis}/js-bun-redis.mdc +0 -0
  119. /package/{policy/js_bun_redis → rules/js-bun-redis/policy}/package_json/package_json.rego +0 -0
  120. /package/{mdc → rules/js-lint}/js-lint.mdc +0 -0
  121. /package/{policy/js_lint → rules/js-lint/policy}/lint_js_yml/lint_js_yml.rego +0 -0
  122. /package/{policy/js_lint → rules/js-lint/policy}/package_json/package_json.rego +0 -0
  123. /package/{policy/js_lint → rules/js-lint/policy}/package_json/package_json_test.rego +0 -0
  124. /package/{mdc → rules/js-mssql}/js-mssql.mdc +0 -0
  125. /package/{policy/js_mssql → rules/js-mssql/policy}/package_json/package_json.rego +0 -0
  126. /package/{mdc → rules/js-run}/js-run.mdc +0 -0
  127. /package/{policy/js_run → rules/js-run/policy}/configmap/configmap.rego +0 -0
  128. /package/{policy/js_run → rules/js-run/policy}/jsconfig/jsconfig.rego +0 -0
  129. /package/{policy/js_run → rules/js-run/policy}/jsconfig/jsconfig_test.rego +0 -0
  130. /package/{policy/js_run → rules/js-run/policy}/package_json/package_json.rego +0 -0
  131. /package/{mdc → rules/k8s}/k8s.mdc +0 -0
  132. /package/{policy/k8s → rules/k8s/policy}/base_kustomization/base_kustomization.rego +0 -0
  133. /package/{policy/k8s → rules/k8s/policy}/base_kustomization/base_kustomization_test.rego +0 -0
  134. /package/{policy/k8s → rules/k8s/policy}/base_manifest/base_manifest.rego +0 -0
  135. /package/{policy/k8s → rules/k8s/policy}/base_manifest/base_manifest_test.rego +0 -0
  136. /package/{policy/k8s → rules/k8s/policy}/gateway/gateway.rego +0 -0
  137. /package/{policy/k8s → rules/k8s/policy}/gateway/gateway_test.rego +0 -0
  138. /package/{policy/k8s → rules/k8s/policy}/hasura_configmap/hasura_configmap.rego +0 -0
  139. /package/{policy/k8s → rules/k8s/policy}/hasura_configmap/hasura_configmap_test.rego +0 -0
  140. /package/{policy/k8s → rules/k8s/policy}/hasura_httproute/hasura_httproute.rego +0 -0
  141. /package/{policy/k8s → rules/k8s/policy}/hasura_httproute/hasura_httproute_test.rego +0 -0
  142. /package/{policy/k8s → rules/k8s/policy}/hpa_pdb/hpa_pdb.rego +0 -0
  143. /package/{policy/k8s → rules/k8s/policy}/hpa_pdb/hpa_pdb_test.rego +0 -0
  144. /package/{policy/k8s → rules/k8s/policy}/kustomization/kustomization.rego +0 -0
  145. /package/{policy/k8s → rules/k8s/policy}/kustomization/kustomization_test.rego +0 -0
  146. /package/{policy/k8s → rules/k8s/policy}/manifest/manifest.rego +0 -0
  147. /package/{policy/k8s → rules/k8s/policy}/manifest/manifest_test.rego +0 -0
  148. /package/{policy/k8s → rules/k8s/policy}/svc_hl_yaml/svc_hl_yaml.rego +0 -0
  149. /package/{policy/k8s → rules/k8s/policy}/svc_hl_yaml/svc_hl_yaml_test.rego +0 -0
  150. /package/{policy/k8s → rules/k8s/policy}/svc_yaml/svc_yaml.rego +0 -0
  151. /package/{policy/k8s → rules/k8s/policy}/svc_yaml/svc_yaml_test.rego +0 -0
  152. /package/{mdc → rules/nginx-default-tpl}/nginx-default-tpl.mdc +0 -0
  153. /package/{policy/nginx_default_tpl → rules/nginx-default-tpl/policy}/vscode_extensions/vscode_extensions.rego +0 -0
  154. /package/{policy/nginx_default_tpl → rules/nginx-default-tpl/policy}/vscode_extensions/vscode_extensions_test.rego +0 -0
  155. /package/{policy/nginx_default_tpl → rules/nginx-default-tpl/policy}/vscode_settings/vscode_settings.rego +0 -0
  156. /package/{policy/nginx_default_tpl → rules/nginx-default-tpl/policy}/vscode_settings/vscode_settings_test.rego +0 -0
  157. /package/{mdc → rules/npm-module}/npm-module.mdc +0 -0
  158. /package/{policy/npm_module → rules/npm-module/policy}/emit_types_config/emit_types_config.rego +0 -0
  159. /package/{policy/npm_module → rules/npm-module/policy}/npm_package_json/npm_package_json.rego +0 -0
  160. /package/{policy/npm_module → rules/npm-module/policy}/npm_package_json/npm_package_json_test.rego +0 -0
  161. /package/{policy/npm_module → rules/npm-module/policy}/npm_publish_yml/npm_publish_yml.rego +0 -0
  162. /package/{policy/npm_module → rules/npm-module/policy}/root_package_json/root_package_json.rego +0 -0
  163. /package/{mdc → rules/php}/php.mdc +0 -0
  164. /package/{policy/php → rules/php/policy}/lint_php_yml/lint_php_yml.rego +0 -0
  165. /package/{policy/php → rules/php/policy}/package_json/package_json.rego +0 -0
  166. /package/{policy/rego → rules/rego/policy}/package_json/package_json.rego +0 -0
  167. /package/{policy/rego → rules/rego/policy}/package_json/package_json_test.rego +0 -0
  168. /package/{policy/rego → rules/rego/policy}/vscode_extensions/vscode_extensions.rego +0 -0
  169. /package/{policy/rego → rules/rego/policy}/vscode_extensions/vscode_extensions_test.rego +0 -0
  170. /package/{policy/rego → rules/rego/policy}/vscode_settings/vscode_settings.rego +0 -0
  171. /package/{policy/rego → rules/rego/policy}/vscode_settings/vscode_settings_test.rego +0 -0
  172. /package/{mdc → rules/rego}/rego.mdc +0 -0
  173. /package/{policy/style_lint → rules/style-lint/policy}/lint_style_yml/lint_style_yml.rego +0 -0
  174. /package/{policy/style_lint → rules/style-lint/policy}/package_json/package_json.rego +0 -0
  175. /package/{policy/style_lint → rules/style-lint/policy}/vscode_extensions/vscode_extensions.rego +0 -0
  176. /package/{policy/style_lint → rules/style-lint/policy}/vscode_extensions/vscode_extensions_test.rego +0 -0
  177. /package/{policy/style_lint → rules/style-lint/policy}/vscode_settings/vscode_settings.rego +0 -0
  178. /package/{policy/style_lint → rules/style-lint/policy}/vscode_settings/vscode_settings_test.rego +0 -0
  179. /package/{mdc → rules/style-lint}/style-lint.mdc +0 -0
  180. /package/{policy/tauri → rules/tauri/policy}/vscode_extensions/vscode_extensions.rego +0 -0
  181. /package/{policy/tauri → rules/tauri/policy}/vscode_extensions/vscode_extensions_test.rego +0 -0
  182. /package/{mdc → rules/tauri}/tauri.mdc +0 -0
  183. /package/{policy/text → rules/text/policy}/cspell/cspell.rego +0 -0
  184. /package/{policy/text → rules/text/policy}/markdownlint/markdownlint.rego +0 -0
  185. /package/{policy/text → rules/text/policy}/markdownlint/markdownlint_test.rego +0 -0
  186. /package/{policy/text → rules/text/policy}/oxfmtrc/oxfmtrc.rego +0 -0
  187. /package/{policy/text → rules/text/policy}/package_json/package_json.rego +0 -0
  188. /package/{policy/text → rules/text/policy}/vscode_extensions/vscode_extensions.rego +0 -0
  189. /package/{policy/text → rules/text/policy}/vscode_extensions/vscode_extensions_test.rego +0 -0
  190. /package/{policy/text → rules/text/policy}/vscode_settings/vscode_settings.rego +0 -0
  191. /package/{policy/text → rules/text/policy}/vscode_settings/vscode_settings_test.rego +0 -0
  192. /package/{policy/vue → rules/vue/policy}/package_json/package_json.rego +0 -0
  193. /package/{mdc → rules/vue}/vue.mdc +0 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,30 @@
4
4
 
5
5
  Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
6
6
 
7
+ ## [1.9.23] - 2026-05-14
8
+
9
+ ### Fixed
10
+
11
+ - `npm/package.json#files`: додано негативні glob-патерни `!**/*.test.mjs`, `!**/test-helpers.mjs`, `!**/fixtures/**`, щоб після переїзду тестів у `rules/<rule>/js/`, `scripts/`, `scripts/utils/` вони не потрапляли в опубліковану npm-таrball (вимагає правило `npm-module`).
12
+ - `npm/package.json#devDependencies`: додано `@nitra/cursor: ^1.9.22` (auto-fill від `ensure-nitra-cursor-dev-dependencies.mjs`).
13
+
14
+ ## [1.9.22] - 2026-05-14
15
+
16
+ ### Changed
17
+
18
+ - **Rule-centric структура пакета.** Кожне правило тепер живе в одній директорії `npm/rules/{rule}/` з усіма своїми артефактами: `{rule}.mdc`, `auto.md` (умова автоактивації), `policy/` (rego-поліси), `js/` (check.mjs + опційні run/lint + co-located *.test.mjs + fixtures/). Видалив каталог правила — правило зникло без слідів у `bin/auto-rules.md`, `npm/policy/`, `npm/scripts/`. Дзеркальна структура для скілів у `npm/skills/{skill}/` (SKILL.md + auto.md + js/).
19
+ - **Тести співрозташовуються з джерелами.** ~50 файлів з `npm/tests/` переїхали в `npm/rules/{rule}/js/*.test.mjs` (тести правил), `npm/scripts/*.test.mjs` (тести інфраструктури), `npm/scripts/utils/*.test.mjs` (тести утиліт). `tests/helpers.mjs` → `scripts/utils/test-helpers.mjs`. `npm/tests/` залишається тільки для 3 крос-правильних інтеграційних тестів.
20
+ - **`bin/n-cursor.js`**: `BUNDLED_MDC_DIR` → `BUNDLED_RULES_DIR`. `discoverBundledRuleNames` і `discoverCheckScripts` тепер обходять підкаталоги `rules/` замість файлів у `mdc/` чи `check-*.mjs` у `scripts/`. Резолвер check-скриптів: `rules/{rule}/js/check.mjs`. `readBundledRuleContent` читає `rules/{rule}/{rule}.mdc`.
21
+ - **`scripts/utils/run-conftest-batch.mjs` та `scripts/lint-conftest.mjs`**: шляхи до rego-полісі — `rules/{rule}/policy/{name}/` (замість `policy/{rule}/{name}/`). Snake_case `policyDirRel` у JS-call sites замінено на kebab-case.
22
+ - **`npm/package.json#files`**: `mdc` і `policy` видалено, додано `rules`. `scripts.test`: `bun test tests` → `bun test` (рекурсивний пошук `*.test.mjs`).
23
+ - **`.cursor/rules/scripts.mdc`** (v1.5): додано секцію «Структура правила» з документацією rule-centric layout для майбутніх правил. Path-references у `npm/CLAUDE.md` оновлено.
24
+
25
+ ### Removed
26
+
27
+ - `npm/mdc/` (24 файли) — вміст переїхав у `npm/rules/{rule}/{rule}.mdc`.
28
+ - `npm/policy/` (24 каталоги) — вміст переїхав у `npm/rules/{rule}/policy/`.
29
+ - `npm/bin/auto-rules.md`, `npm/bin/auto-skills.md` — замінено на per-rule і per-skill `auto.md` в кожному каталозі.
30
+
7
31
  ## [1.9.20] - 2026-05-14
8
32
 
9
33
  ### Added
package/bin/n-cursor.js CHANGED
@@ -21,7 +21,7 @@
21
21
  *
22
22
  * Якщо у корені репозиторію немає .n-cursor.json, спочатку перейменовується за наявності nitra-cursor.json;
23
23
  * у `.cursor/rules` файли `nitra-*.mdc` перейменовуються на `n-*.mdc`; інакше конфіг створюється автоматично
24
- * з усіма правилами з каталогу mdc пакету (їх можна відредагувати після створення). У файлі завжди має бути
24
+ * з усіма правилами з каталогу rules/ пакету (їх можна відредагувати після створення). У файлі завжди має бути
25
25
  * поле `$schema` з посиланням на JSON Schema пакету (публічний URL для IDE); при зчитуванні конфігу воно додається або виправляється на диску, якщо відсутнє або некоректне.
26
26
  * Масиви `rules`, `skills`, `disable-rules` і `disable-skills` при записі сортуються за алфавітом.
27
27
  *
@@ -36,7 +36,7 @@
36
36
  * `github-actions/` пакету при кожному успішному синку (workflows з правил ga / js-lint / text).
37
37
  *
38
38
  * Skills копіюються з npm/skills пакету лише для id з масиву «skills» у .n-cursor.json
39
- * (у JSON — без префікса, як імена файлів у mdc/ без n-). У пакеті джерело — каталоги
39
+ * (у JSON — без префікса, як імена каталогів у rules/ без n-). У пакеті джерело — каталоги
40
40
  * skills/<id>/ (без префікса); у проєкті — .cursor/skills/n-<id>/ (префікс n-, як n-*.mdc).
41
41
  * Якщо ключа skills немає, за замовчуванням підтягуються всі підкаталоги skills/ (лише імена без префікса n-).
42
42
  * Зайві каталоги n-* у .cursor/skills, яких немає у списку, видаляються.
@@ -67,7 +67,7 @@ import {
67
67
  import { detectAutoSkills } from '../scripts/auto-skills.mjs'
68
68
  import { runStopHookCli } from '../scripts/claude-stop-hook.mjs'
69
69
  import { ensureNitraCursorInRootDevDependencies } from '../scripts/ensure-nitra-cursor-dev-dependencies.mjs'
70
- import { runLintGaCli } from '../scripts/lint-ga.mjs'
70
+ import { runLintGaCli } from '../rules/ga/js/lint.mjs'
71
71
  import { syncClaudeConfig } from '../scripts/sync-claude-config.mjs'
72
72
  import { upgradeNitraCursorToLatestAndBunInstall } from '../scripts/upgrade-nitra-cursor-and-install.mjs'
73
73
  import { runRenameYamlExtensionsCli } from './rename-yaml-extensions.mjs'
@@ -85,11 +85,11 @@ const COMMANDS_DIR = '.claude/commands'
85
85
  const RULE_PREFIX = 'n-'
86
86
 
87
87
  const binDir = dirname(fileURLToPath(import.meta.url))
88
- const BUNDLED_MDC_DIR = join(binDir, '..', 'mdc')
88
+ const BUNDLED_RULES_DIR = join(binDir, '..', 'rules')
89
89
  const BUNDLED_SCRIPTS_DIR = join(binDir, '..', 'scripts')
90
90
  const BUNDLED_SKILLS_DIR = join(binDir, '..', 'skills')
91
91
  const BUNDLED_AGENTS_TEMPLATE_PATH = join(binDir, '..', AGENTS_TEMPLATE_FILE)
92
- /** Корінь установленого пакету (каталог з `mdc/`, `github-actions/`, …) */
92
+ /** Корінь установленого пакету (каталог з `rules/`, `github-actions/`, …) */
93
93
  const BUNDLED_PACKAGE_ROOT = join(binDir, '..')
94
94
 
95
95
  const YAML_FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---/
@@ -116,25 +116,27 @@ function sortConfigIdArrays(config) {
116
116
  }
117
117
 
118
118
  /**
119
- * Імена правил (без .mdc) з каталогу mdc поточної інсталяції пакету
120
- * @param {string} [bundledMdcDir] каталог `mdc/` у корені пакету (за замовчуванням — з поточного процесу)
121
- * @returns {Promise<string[]>} відсортовані імена файлів правил без суфікса .mdc
119
+ * Імена правил з каталогу `rules/` поточної інсталяції пакету. Кожне правило — окремий
120
+ * підкаталог `rules/<id>/`, у якому має бути `<id>.mdc`.
121
+ * @param {string} [bundledRulesDir] каталог `rules/` у корені пакету
122
+ * @returns {Promise<string[]>} відсортовані id правил (імена підкаталогів)
122
123
  */
123
- async function discoverBundledRuleNames(bundledMdcDir = BUNDLED_MDC_DIR) {
124
- if (!existsSync(bundledMdcDir)) {
124
+ async function discoverBundledRuleNames(bundledRulesDir = BUNDLED_RULES_DIR) {
125
+ if (!existsSync(bundledRulesDir)) {
125
126
  throw new Error(
126
127
  `Не знайдено каталог правил пакету.\n` +
127
- `Очікуваний шлях: ${bundledMdcDir}\n` +
128
+ `Очікуваний шлях: ${bundledRulesDir}\n` +
128
129
  `Перевстановіть ${PACKAGE_NAME} або створіть ${CONFIG_FILE} вручну.`
129
130
  )
130
131
  }
131
- const names = await readdir(bundledMdcDir)
132
- const rules = names
133
- .filter(n => n.endsWith('.mdc'))
134
- .map(n => n.slice(0, -'.mdc'.length))
132
+ const entries = await readdir(bundledRulesDir, { withFileTypes: true })
133
+ const rules = entries
134
+ .filter(e => e.isDirectory() && !e.name.startsWith('.'))
135
+ .filter(e => existsSync(join(bundledRulesDir, e.name, `${e.name}.mdc`)))
136
+ .map(e => e.name)
135
137
  .toSorted((a, b) => a.localeCompare(b))
136
138
  if (rules.length === 0) {
137
- throw new Error(`У каталозі mdc пакету немає файлів .mdc. Створіть ${CONFIG_FILE} вручну.`)
139
+ throw new Error(`У каталозі rules/ пакету немає підкаталогів з <id>.mdc. Створіть ${CONFIG_FILE} вручну.`)
138
140
  }
139
141
  return rules
140
142
  }
@@ -203,15 +205,15 @@ async function migrateLegacyConfigIfNeeded() {
203
205
 
204
206
  /**
205
207
  * Зчитує конфіг .n-cursor.json з поточної директорії
206
- * @param {{ bundledMdcDir?: string, bundledSkillsDir?: string }} [paths] каталоги з пакету-джерела (після `bun i` — зазвичай `node_modules/@nitra/cursor`)
208
+ * @param {{ bundledRulesDir?: string, bundledSkillsDir?: string }} [paths] каталоги з пакету-джерела (після `bun i` — зазвичай `node_modules/@nitra/cursor`)
207
209
  * @returns {Promise<{ $schema: string, rules: string[], skills: string[], version?: string } & Record<string, unknown>>} rules, skills (id без префікса n-); поле version у файлі за наявності ігнорується при синхронізації правил
208
210
  */
209
211
  async function readConfig(paths = {}) {
210
- const bundledMdcDir = paths.bundledMdcDir ?? BUNDLED_MDC_DIR
212
+ const bundledRulesDir = paths.bundledRulesDir ?? BUNDLED_RULES_DIR
211
213
  const bundledSkillsDir = paths.bundledSkillsDir ?? BUNDLED_SKILLS_DIR
212
214
  await migrateLegacyConfigIfNeeded()
213
215
  const configPath = join(cwd(), CONFIG_FILE)
214
- const availableRules = await discoverBundledRuleNames(bundledMdcDir)
216
+ const availableRules = await discoverBundledRuleNames(bundledRulesDir)
215
217
  const availableSkills = await discoverBundledSkillNames(bundledSkillsDir)
216
218
 
217
219
  /**
@@ -231,7 +233,7 @@ async function readConfig(paths = {}) {
231
233
  }
232
234
 
233
235
  /**
234
- * Автодописує правила/skills за `auto-rules.md` і синхронізує `$schema`.
236
+ * Автодописує правила/skills за `rules/<rule>/auto.md` і синхронізує `$schema`.
235
237
  * @param {Record<string, unknown>} parsedConfig сирий обʼєкт конфігу
236
238
  * @returns {Promise<Record<string, unknown>>} нормалізований конфіг
237
239
  */
@@ -350,29 +352,31 @@ function logRuleMigrationsIfAny(parsedConfig) {
350
352
  }
351
353
 
352
354
  /**
353
- * Витягує чисте ім'я файлу правила (без шляху, але зберігає .mdc)
354
- * "npm/mdc/text.mdc" → "text.mdc"
355
- * "text" → "text.mdc"
355
+ * Витягує чистий id правила без шляху і без .mdc.
356
+ * "npm/rules/text/text.mdc" → "text"
357
+ * "text.mdc" → "text"
358
+ * "text" → "text"
356
359
  * @param {string} ruleName шлях або базове ім'я, з суфіксом .mdc або без
357
- * @returns {string} лише ім'я файлу з суфіксом .mdc
360
+ * @returns {string} id правила (без .mdc, без шляху)
358
361
  */
359
362
  function normalizeRuleName(ruleName) {
360
- const name = ruleName.endsWith('.mdc') ? ruleName : `${ruleName}.mdc`
361
- return basename(name)
363
+ const name = basename(String(ruleName).trim())
364
+ return name.endsWith('.mdc') ? name.slice(0, -'.mdc'.length) : name
362
365
  }
363
366
 
364
367
  /**
365
- * Читає вміст правила з каталогу `mdc/` установленого пакету (наприклад `node_modules/@nitra/cursor/mdc` або кеш npx).
368
+ * Читає вміст правила з каталогу `rules/<id>/<id>.mdc` установленого пакету
369
+ * (наприклад `node_modules/@nitra/cursor/rules/<id>/<id>.mdc` або кеш npx).
366
370
  * @param {string} rule елемент масиву rules з `.n-cursor.json`
367
- * @param {string} [bundledMdcDir] каталог `mdc/` у корені пакету-джерела
371
+ * @param {string} [bundledRulesDir] каталог `rules/` у корені пакету-джерела
368
372
  * @returns {Promise<string>} текст правила для запису в `.cursor/rules/n-*.mdc`
369
373
  */
370
- function readBundledRuleContent(rule, bundledMdcDir = BUNDLED_MDC_DIR) {
371
- const bundledName = normalizeRuleName(rule)
372
- const bundledPath = join(bundledMdcDir, bundledName)
374
+ function readBundledRuleContent(rule, bundledRulesDir = BUNDLED_RULES_DIR) {
375
+ const id = normalizeRuleName(rule)
376
+ const bundledPath = join(bundledRulesDir, id, `${id}.mdc`)
373
377
  if (!existsSync(bundledPath)) {
374
378
  throw new Error(
375
- `Немає файлу ${bundledName} у ${bundledMdcDir}. Оновіть ${PACKAGE_NAME} або приберіть "${rule}" з rules у ${CONFIG_FILE}.`
379
+ `Немає файлу ${id}/${id}.mdc у ${bundledRulesDir}. Оновіть ${PACKAGE_NAME} або приберіть "${rule}" з rules у ${CONFIG_FILE}.`
376
380
  )
377
381
  }
378
382
  return readFile(bundledPath, 'utf8')
@@ -515,7 +519,7 @@ async function listProjectRulesMdcFiles() {
515
519
  * @returns {Set<string>} множина очікуваних імен файлів (наприклад n-bun.mdc)
516
520
  */
517
521
  function expectedManagedRuleBasenames(configRules) {
518
- return new Set(configRules.map(rule => `${RULE_PREFIX}${normalizeRuleName(rule)}`))
522
+ return new Set(configRules.map(rule => `${RULE_PREFIX}${normalizeRuleName(rule)}.mdc`))
519
523
  }
520
524
 
521
525
  /**
@@ -939,19 +943,19 @@ async function runSyncStep(prefix, action) {
939
943
  /**
940
944
  * Копіює керовані `.mdc` файли з пакету до `.cursor/rules`.
941
945
  * @param {string[]} rules список rules з конфігу
942
- * @param {string} bundledMdcDir каталог `mdc` пакету-джерела
946
+ * @param {string} bundledRulesDir каталог `mdc` пакету-джерела
943
947
  * @param {string} rulesDir абсолютний шлях до `.cursor/rules`
944
948
  * @returns {Promise<{ successCount: number, failCount: number }>} статистика копіювання
945
949
  */
946
- async function syncManagedRuleFiles(rules, bundledMdcDir, rulesDir) {
950
+ async function syncManagedRuleFiles(rules, bundledRulesDir, rulesDir) {
947
951
  let successCount = 0
948
952
  let failCount = 0
949
953
  for (const rule of rules) {
950
- const fileName = `${RULE_PREFIX}${normalizeRuleName(rule)}`
954
+ const fileName = `${RULE_PREFIX}${normalizeRuleName(rule)}.mdc`
951
955
  const destPath = join(rulesDir, fileName)
952
956
  try {
953
957
  process.stdout.write(` ⬇ ${rule} → ${RULES_DIR}/${fileName} ... `)
954
- const content = await readBundledRuleContent(rule, bundledMdcDir)
958
+ const content = await readBundledRuleContent(rule, bundledRulesDir)
955
959
  await writeFile(destPath, content, 'utf8')
956
960
  console.log(`✅`)
957
961
  successCount++
@@ -982,15 +986,17 @@ function logRemovedManagedItems(title, basePath, names) {
982
986
  }
983
987
 
984
988
  /**
985
- * Знаходить доступні check-скрипти у каталозі scripts пакету
986
- * @returns {Promise<string[]>} відсортовані імена правил (наприклад ['bun', 'ga', 'js-lint'])
989
+ * Знаходить доступні check-скрипти. Кожне правило з check-скриптом тримає його у
990
+ * `rules/<id>/js/check.mjs` (rule-centric layout).
991
+ * @returns {Promise<string[]>} відсортовані id правил, для яких є check.mjs
987
992
  */
988
993
  async function discoverCheckScripts() {
989
- if (!existsSync(BUNDLED_SCRIPTS_DIR)) return []
990
- const names = await readdir(BUNDLED_SCRIPTS_DIR)
991
- return names
992
- .filter(n => n.startsWith('check-') && n.endsWith('.mjs'))
993
- .map(n => n.slice('check-'.length, -'.mjs'.length))
994
+ if (!existsSync(BUNDLED_RULES_DIR)) return []
995
+ const entries = await readdir(BUNDLED_RULES_DIR, { withFileTypes: true })
996
+ return entries
997
+ .filter(e => e.isDirectory() && !e.name.startsWith('.'))
998
+ .filter(e => existsSync(join(BUNDLED_RULES_DIR, e.name, 'js', 'check.mjs')))
999
+ .map(e => e.name)
994
1000
  .toSorted((a, b) => a.localeCompare(b))
995
1001
  }
996
1002
 
@@ -1090,10 +1096,10 @@ async function runChecks(requestedRules) {
1090
1096
  let totalFailed = 0
1091
1097
 
1092
1098
  for (const rule of rulesToCheck) {
1093
- const scriptPath = join(BUNDLED_SCRIPTS_DIR, `check-${rule}.mjs`)
1099
+ const scriptPath = join(BUNDLED_RULES_DIR, rule, 'js', 'check.mjs')
1094
1100
  console.log(`📋 ${rule}:`)
1095
1101
  try {
1096
- // eslint-disable-next-line no-unsanitized/method -- rule валідовано проти available, scriptPath будується з фіксованої BUNDLED_SCRIPTS_DIR
1102
+ // eslint-disable-next-line no-unsanitized/method -- rule валідовано проти available, scriptPath будується з фіксованої BUNDLED_RULES_DIR
1097
1103
  const { check } = await import(scriptPath)
1098
1104
  const code = await check()
1099
1105
  if (code !== 0) totalFailed++
@@ -1201,11 +1207,11 @@ async function runSync() {
1201
1207
 
1202
1208
  await reexecIfPackageVersionChanged(effectivePackageRoot)
1203
1209
 
1204
- const bundledMdcDir = join(effectivePackageRoot, 'mdc')
1210
+ const bundledRulesDir = join(effectivePackageRoot, 'mdc')
1205
1211
  const bundledSkillsDir = join(effectivePackageRoot, 'skills')
1206
1212
  const bundledAgentsTemplatePath = join(effectivePackageRoot, AGENTS_TEMPLATE_FILE)
1207
1213
 
1208
- const config = await runSyncStep('❌ ', () => readConfig({ bundledMdcDir, bundledSkillsDir }))
1214
+ const config = await runSyncStep('❌ ', () => readConfig({ bundledRulesDir, bundledSkillsDir }))
1209
1215
 
1210
1216
  const { rules, skills, version, ignore } = config
1211
1217
  const claudeConfigEnabled = config['claude-config'] !== false
@@ -1230,7 +1236,7 @@ async function runSync() {
1230
1236
 
1231
1237
  const rulesDir = join(cwd(), RULES_DIR)
1232
1238
  await mkdir(rulesDir, { recursive: true })
1233
- const { successCount, failCount } = await syncManagedRuleFiles(rules, bundledMdcDir, rulesDir)
1239
+ const { successCount, failCount } = await syncManagedRuleFiles(rules, bundledRulesDir, rulesDir)
1234
1240
 
1235
1241
  await runSyncStep(`❌ Не вдалося прибрати зайві файли в ${RULES_DIR}: `, async () => {
1236
1242
  const removed = await removeOrphanManagedRuleFiles(rulesDir, rules)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitra/cursor",
3
- "version": "1.9.20",
3
+ "version": "1.9.23",
4
4
  "description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
5
5
  "keywords": [
6
6
  "cli",
@@ -24,21 +24,23 @@
24
24
  },
25
25
  "files": [
26
26
  "types",
27
- "mdc",
27
+ "rules",
28
28
  "bin",
29
29
  "github-actions",
30
- "policy",
31
30
  "schemas",
32
31
  "scripts",
33
32
  "skills",
34
33
  ".claude-template",
35
34
  "AGENTS.template.md",
36
- "CHANGELOG.md"
35
+ "CHANGELOG.md",
36
+ "!**/*.test.mjs",
37
+ "!**/test-helpers.mjs",
38
+ "!**/fixtures/**"
37
39
  ],
38
40
  "type": "module",
39
41
  "types": "./types/bin/n-cursor.d.ts",
40
42
  "scripts": {
41
- "test": "bun test tests",
43
+ "test": "bun test",
42
44
  "rename-yaml-extensions": "bun ./bin/n-cursor.js rename-yaml-extensions"
43
45
  },
44
46
  "dependencies": {
@@ -48,5 +50,8 @@
48
50
  "engines": {
49
51
  "bun": ">=1.3",
50
52
  "node": ">=25"
53
+ },
54
+ "devDependencies": {
55
+ "@nitra/cursor": "^1.9.22"
51
56
  }
52
57
  }
@@ -0,0 +1 @@
1
+ якщо в кореневому package.json в секції "repository" присутній текст "<https://github.com/abinbevefes/**/>"
@@ -45,11 +45,11 @@ import { basename, dirname, join, relative } from 'node:path'
45
45
 
46
46
  import { parseAllDocuments } from 'yaml'
47
47
 
48
- import { pathHasK8sSegment } from './check-k8s.mjs'
49
- import { createCheckReporter } from './utils/check-reporter.mjs'
50
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
51
- import { runConftestBatch } from './utils/run-conftest-batch.mjs'
52
- import { walkDir } from './utils/walkDir.mjs'
48
+ import { pathHasK8sSegment } from '../../k8s/js/check.mjs'
49
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
50
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
51
+ import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
52
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
53
53
 
54
54
  const CONFIG_FILE = '.n-cursor.json'
55
55
 
@@ -19,7 +19,7 @@ import { delimiter, dirname, join } from 'node:path'
19
19
  import { env } from 'node:process'
20
20
  import { fileURLToPath } from 'node:url'
21
21
 
22
- import { createCheckReporter } from './utils/check-reporter.mjs'
22
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
23
23
 
24
24
  const PROJECT_HOOK_PATH = '.claude/hooks/capture-decisions.sh'
25
25
  const PROJECT_SETTINGS_PATH = '.claude/settings.json'
@@ -0,0 +1 @@
1
+ якщо в корені проекту є package.json
@@ -18,7 +18,7 @@
18
18
  import { existsSync } from 'node:fs'
19
19
  import { readFile } from 'node:fs/promises'
20
20
 
21
- import { createCheckReporter } from './utils/check-reporter.mjs'
21
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
22
22
 
23
23
  // Перевірка `devDependencies` кореневого `package.json` (дозволено лише `@nitra/*`)
24
24
  // — у rego (`npm/policy/bun/package_json/`). JS-копії `isAllowedRootDevDependency`
@@ -0,0 +1 @@
1
+ якщо в проекті є хоч один файл capacitor.config.json
@@ -25,7 +25,7 @@ import { existsSync } from 'node:fs'
25
25
  import { readdir, readFile } from 'node:fs/promises'
26
26
  import { join, relative } from 'node:path'
27
27
 
28
- import { createCheckReporter } from './utils/check-reporter.mjs'
28
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
29
29
 
30
30
  /** Мінімальна допустима мажорна версія Capacitor (capacitor.mdc) */
31
31
  const MIN_CAPACITOR_MAJOR = 8
@@ -0,0 +1 @@
1
+ [bun]
@@ -27,8 +27,8 @@ import { readFile } from 'node:fs/promises'
27
27
  import { join } from 'node:path'
28
28
  import { promisify } from 'node:util'
29
29
 
30
- import { createCheckReporter } from './utils/check-reporter.mjs'
31
- import { getMonorepoPackageRootDirs } from './utils/workspaces.mjs'
30
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
31
+ import { getMonorepoPackageRootDirs } from '../../../scripts/utils/workspaces.mjs'
32
32
 
33
33
  const execFileAsync = promisify(execFile)
34
34
 
@@ -0,0 +1 @@
1
+ якщо в проекті є хоч один Dockerfile
@@ -30,11 +30,11 @@
30
30
  import { readFile } from 'node:fs/promises'
31
31
  import { basename } from 'node:path'
32
32
 
33
- import { getMirrorGcrHint, getFromImageToken } from './utils/docker-mirror.mjs'
34
- import { lintDockerfileWithHadolint, posixRel } from './utils/docker-hadolint.mjs'
35
- import { createCheckReporter } from './utils/check-reporter.mjs'
36
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
37
- import { walkDir } from './utils/walkDir.mjs'
33
+ import { getMirrorGcrHint, getFromImageToken } from '../../../scripts/utils/docker-mirror.mjs'
34
+ import { lintDockerfileWithHadolint, posixRel } from '../../../scripts/utils/docker-hadolint.mjs'
35
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
36
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
37
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
38
38
 
39
39
  const NEWLINE_RE = /\r?\n/
40
40
  const BUN_INSTALL_RE = /\bbun\s+(?:install|i)\b/iu
@@ -9,11 +9,11 @@
9
9
  */
10
10
  import { basename } from 'node:path'
11
11
 
12
- import { isRunAsCli } from './cli-entry.mjs'
13
- import { lintDockerfileWithHadolint, posixRel } from './utils/docker-hadolint.mjs'
14
- import { createCheckReporter } from './utils/check-reporter.mjs'
15
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
16
- import { walkDir } from './utils/walkDir.mjs'
12
+ import { isRunAsCli } from '../../../scripts/cli-entry.mjs'
13
+ import { lintDockerfileWithHadolint, posixRel } from '../../../scripts/utils/docker-hadolint.mjs'
14
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
15
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
16
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
17
17
 
18
18
  /**
19
19
  * Чи входить файл до набору lint-docker: Dockerfile або *.Dockerfile (*.dockerfile).
@@ -0,0 +1 @@
1
+ якщо присутня директорія .github/workflows
@@ -19,10 +19,10 @@ import { readdir, readFile } from 'node:fs/promises'
19
19
  import { execFileSync } from 'node:child_process'
20
20
  import { join } from 'node:path'
21
21
 
22
- import { createCheckReporter } from './utils/check-reporter.mjs'
23
- import { eventPathsIncludeExact, parseWorkflowYaml } from './utils/gha-workflow.mjs'
24
- import { resolveCmd } from './utils/resolve-cmd.mjs'
25
- import { runConftestBatch } from './utils/run-conftest-batch.mjs'
22
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
23
+ import { eventPathsIncludeExact, parseWorkflowYaml } from '../../../scripts/utils/gha-workflow.mjs'
24
+ import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
25
+ import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
26
26
 
27
27
  /** Шаблони наявності MegaLinter у вмісті workflow */
28
28
  const MEGALINTER_USE_PATTERNS = [/oxsecurity\/megalinter-action/i, /megalinter\/megalinter/i]
@@ -22,8 +22,8 @@
22
22
  import { spawnSync } from 'node:child_process'
23
23
  import { platform } from 'node:process'
24
24
 
25
- import { check as checkGa } from './check-ga.mjs'
26
- import { resolveCmd } from './utils/resolve-cmd.mjs'
25
+ import { check as checkGa } from './check.mjs'
26
+ import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
27
27
 
28
28
  /**
29
29
  * Опис залежності preflight-ом: бінарник, для чого потрібен, і команди встановлення.
@@ -0,0 +1 @@
1
+ якщо хоч в одному js або vue файлі присутній gql` темплейт літерал
@@ -10,15 +10,15 @@ import { existsSync } from 'node:fs'
10
10
  import { readFile } from 'node:fs/promises'
11
11
  import { relative } from 'node:path'
12
12
 
13
- import { createCheckReporter } from './utils/check-reporter.mjs'
13
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
14
14
  import {
15
15
  isGqlScanSourceFile,
16
16
  shouldSkipFileForGqlScan,
17
17
  sourceFileHasGqlTaggedTemplate
18
- } from './utils/graphql-gql-scan.mjs'
19
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
20
- import { runConftestBatch } from './utils/run-conftest-batch.mjs'
21
- import { walkDir } from './utils/walkDir.mjs'
18
+ } from '../../../scripts/utils/graphql-gql-scan.mjs'
19
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
20
+ import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
21
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
22
22
 
23
23
  /** Очікуваний файл GraphQL Config у корені (graphql.mdc). */
24
24
  export const GRAPHQL_RC_FILENAME = '.graphqlrc.yml'
@@ -0,0 +1 @@
1
+ якщо в директорії присутній config.yaml, який містить рядок `metadata_directory: metadata`
@@ -27,10 +27,10 @@ import { basename, join, relative } from 'node:path'
27
27
 
28
28
  import { parseAllDocuments } from 'yaml'
29
29
 
30
- import { getRepositoryUrl } from './auto-rules.mjs'
31
- import { createCheckReporter } from './utils/check-reporter.mjs'
32
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
33
- import { walkDir } from './utils/walkDir.mjs'
30
+ import { getRepositoryUrl } from '../../../scripts/auto-rules.mjs'
31
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
32
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
33
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
34
34
 
35
35
  const NITRA_REPOSITORY_URL_MARKER = 'https://github.com/nitra/'
36
36
  const ABIE_REPOSITORY_URL_MARKER = 'https://github.com/abinbevefes/'
@@ -0,0 +1 @@
1
+ [vue, image-compress]
@@ -25,11 +25,11 @@ import { join, relative } from 'node:path'
25
25
  import { spawnSync } from 'node:child_process'
26
26
  import { env } from 'node:process'
27
27
 
28
- import { createCheckReporter } from './utils/check-reporter.mjs'
29
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
30
- import { resolveCmd } from './utils/resolve-cmd.mjs'
31
- import { walkDir } from './utils/walkDir.mjs'
32
- import { getMonorepoPackageRootDirs } from './utils/workspaces.mjs'
28
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
29
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
30
+ import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
31
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
32
+ import { getMonorepoPackageRootDirs } from '../../../scripts/utils/workspaces.mjs'
33
33
 
34
34
  /** Імʼя CLI-пакета, який генерує AVIF. */
35
35
  const MINIFY_PACKAGE_NAME = '@nitra/minify-image'
@@ -0,0 +1 @@
1
+ [bun]
@@ -19,7 +19,7 @@
19
19
  import { existsSync } from 'node:fs'
20
20
  import { readFile } from 'node:fs/promises'
21
21
 
22
- import { createCheckReporter } from './utils/check-reporter.mjs'
22
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
23
23
 
24
24
  /** Імʼя committed-кешу (sha1 + originalSize + size) у `@nitra/minify-image` ≥ 3.2.0. */
25
25
  const HASH_CACHE_FILENAME = '.n-minify-image.tsv'
@@ -0,0 +1 @@
1
+ якщо в хоч одному package.json в секції dependencies присутній пакет pg, pg-format або mysql2 або є імпорт sql/SQL з Bun (приклад: import { sql } from "bun")
@@ -25,7 +25,7 @@ import { existsSync } from 'node:fs'
25
25
  import { readFile } from 'node:fs/promises'
26
26
  import { join, relative } from 'node:path'
27
27
 
28
- import { createCheckReporter } from './utils/check-reporter.mjs'
28
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
29
29
  import {
30
30
  findBunSqlPerRequestConnectionInText,
31
31
  findBunSqlPgLeftoverCallInText,
@@ -36,10 +36,10 @@ import {
36
36
  findUnsafeBunSqlInListMissingEmptyGuardInText,
37
37
  isBunSqlScanSourceFile,
38
38
  textHasBunSqlImport
39
- } from './utils/bun-sql-scan.mjs'
40
- import { findAllPackageJsonPaths } from './utils/find-package-json-paths.mjs'
41
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
42
- import { walkDir } from './utils/walkDir.mjs'
39
+ } from '../../../scripts/utils/bun-sql-scan.mjs'
40
+ import { findAllPackageJsonPaths } from '../../../scripts/utils/find-package-json-paths.mjs'
41
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
42
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
43
43
 
44
44
  /**
45
45
  * Збирає абсолютні шляхи JS/TS джерел у репозиторії для скану Bun SQL патернів.
@@ -0,0 +1 @@
1
+ якщо в хоч одному package.json в секції dependencies присутній пакет ioredis або node-redis
@@ -14,10 +14,10 @@ import { existsSync } from 'node:fs'
14
14
  import { readFile } from 'node:fs/promises'
15
15
  import { join, relative } from 'node:path'
16
16
 
17
- import { createCheckReporter } from './utils/check-reporter.mjs'
18
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
19
- import { findRedisImportsInText, isRedisScanSourceFile, shouldSkipFileForRedisScan } from './utils/redis-imports.mjs'
20
- import { walkDir } from './utils/walkDir.mjs'
17
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
18
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
19
+ import { findRedisImportsInText, isRedisScanSourceFile, shouldSkipFileForRedisScan } from '../../../scripts/utils/redis-imports.mjs'
20
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
21
21
 
22
22
  /**
23
23
  * Збирає абсолютні шляхи JS/TS джерел у репозиторії для скану заборонених redis-імпортів.
@@ -0,0 +1 @@
1
+ якщо присутній хоч один js файл
@@ -16,7 +16,7 @@ import { copyFile, readFile } from 'node:fs/promises'
16
16
  import { dirname, join } from 'node:path'
17
17
  import { fileURLToPath } from 'node:url'
18
18
 
19
- import { createCheckReporter } from './utils/check-reporter.mjs'
19
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
20
20
 
21
21
  /** Шлях до канонічного oxlint JSON у цьому пакеті (для перевірки та тестів). */
22
22
  export const OXLINT_CANONICAL_JSON_PATH = join(
@@ -0,0 +1 @@
1
+ якщо в хоч одному package.json в секції dependencies присутній пакет mssql