@nitra/cursor 12.8.5 → 12.8.7

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 (202) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/bin/n-cursor.js +5 -5
  3. package/package.json +1 -1
  4. package/rules/abie/js/http_route_base.mdc +25 -0
  5. package/rules/abie/js/ua_http_route.mdc +1 -1
  6. package/rules/abie/main.mdc +12 -0
  7. package/rules/adr/js/hooks.mdc +32 -0
  8. package/rules/adr/js/madr_format.mdc +96 -0
  9. package/rules/adr/js/settings_policy.mdc +34 -0
  10. package/rules/adr/main.mdc +13 -95
  11. package/rules/bun/js/bunfig.mdc +12 -0
  12. package/rules/bun/js/layout.mdc +60 -0
  13. package/rules/bun/js/lint.mdc +9 -0
  14. package/rules/bun/js/package_json.mdc +19 -0
  15. package/rules/bun/main.mdc +9 -61
  16. package/rules/capacitor/js/ios_spm.mdc +69 -0
  17. package/rules/capacitor/js/version.mdc +29 -0
  18. package/rules/capacitor/main.mdc +8 -22
  19. package/rules/changelog/js/agent-workflow.mdc +15 -0
  20. package/rules/changelog/js/changelog-format.mdc +33 -0
  21. package/rules/changelog/js/comparison-models.mdc +40 -0
  22. package/rules/changelog/main.mdc +4 -98
  23. package/rules/ci4/js/marksman_config.mdc +31 -0
  24. package/rules/ci4/js/vscode_extensions.mdc +33 -0
  25. package/rules/ci4/main.mdc +14 -14
  26. package/rules/docker/js/compile.mdc +44 -0
  27. package/rules/docker/js/hadolint.mdc +50 -0
  28. package/rules/docker/js/mirror.mdc +13 -0
  29. package/rules/docker/js/multistage.mdc +13 -0
  30. package/rules/docker/js/native-addon.mdc +43 -0
  31. package/rules/docker/js/nginx-tag.mdc +7 -0
  32. package/rules/docker/js/nginx-user.mdc +37 -0
  33. package/rules/docker/js/non-root.mdc +39 -0
  34. package/rules/docker/main.mdc +15 -196
  35. package/rules/ga/js/lint_toolchain.mdc +15 -0
  36. package/rules/ga/js/required_workflows.mdc +35 -0
  37. package/rules/ga/js/vscode.mdc +17 -0
  38. package/rules/ga/js/workflow_common.mdc +108 -0
  39. package/rules/ga/js/workflows.mdc +32 -0
  40. package/rules/ga/js/zizmor.mdc +7 -0
  41. package/rules/ga/main.mdc +17 -125
  42. package/rules/graphql/js/tooling.mdc +13 -0
  43. package/rules/graphql/js/vscode_extensions.mdc +13 -0
  44. package/rules/graphql/main.mdc +3 -22
  45. package/rules/hasura/js/internal_urls.mdc +27 -0
  46. package/rules/hasura/js/migrations.mdc +13 -0
  47. package/rules/hasura/js/svc_hl.mdc +17 -0
  48. package/rules/hasura/main.mdc +8 -30
  49. package/rules/image-avif/js/avif_generation.mdc +26 -0
  50. package/rules/image-avif/js/package_json_optout.mdc +21 -0
  51. package/rules/image-avif/main.mdc +7 -34
  52. package/rules/image-compress/js/package_json.mdc +7 -0
  53. package/rules/image-compress/js/package_setup.mdc +13 -0
  54. package/rules/image-compress/main.mdc +4 -12
  55. package/rules/js/docs/index.md +3 -3
  56. package/rules/js/js/dep-policy.mdc +17 -0
  57. package/rules/js/js/eslint-config.mdc +28 -0
  58. package/rules/js/js/extensions.mdc +8 -0
  59. package/rules/js/js/file-extensions.mdc +12 -0
  60. package/rules/js/js/for-in.mdc +26 -0
  61. package/rules/js/js/jscpd.mdc +42 -0
  62. package/rules/js/js/knip.mdc +15 -0
  63. package/rules/js/js/lint-js-workflow.mdc +58 -0
  64. package/rules/js/js/oxlintrc.mdc +20 -0
  65. package/rules/js/js/package-json.mdc +31 -0
  66. package/rules/js/js/tests.mdc +9 -0
  67. package/rules/js/js/utils-lib-structure.mdc +15 -0
  68. package/rules/js/main.mdc +21 -214
  69. package/rules/js-bun-db/js/bun-sql-migration.mdc +15 -0
  70. package/rules/js-bun-db/js/connection.mdc +42 -0
  71. package/rules/js-bun-db/js/pg-format-identifiers.mdc +102 -0
  72. package/rules/js-bun-db/js/pg-format-shim.mdc +99 -0
  73. package/rules/js-bun-db/js/pg-leftover.mdc +27 -0
  74. package/rules/js-bun-db/js/pg-listen-notify.mdc +51 -0
  75. package/rules/js-bun-db/js/query-safety.mdc +117 -0
  76. package/rules/js-bun-db/js/sql-array.mdc +88 -0
  77. package/rules/js-bun-db/js/unsafe.mdc +65 -0
  78. package/rules/js-bun-db/main.mdc +15 -605
  79. package/rules/js-bun-redis/js/imports.mdc +47 -0
  80. package/rules/js-bun-redis/js/package_json.mdc +44 -0
  81. package/rules/js-bun-redis/main.mdc +3 -11
  82. package/rules/js-mssql/js/mssql-in-list.mdc +38 -0
  83. package/rules/js-mssql/js/mssql-pool.mdc +56 -0
  84. package/rules/js-mssql/js/mssql-query-template.mdc +33 -0
  85. package/rules/js-mssql/js/mssql-tvp.mdc +75 -0
  86. package/rules/js-mssql/js/mssql-version.mdc +7 -0
  87. package/rules/js-mssql/main.mdc +10 -198
  88. package/rules/js-run/js/check-env.mdc +35 -0
  89. package/rules/js-run/js/conn-aliases.mdc +109 -0
  90. package/rules/js-run/js/jsconfig.mdc +20 -0
  91. package/rules/js-run/js/otel-configmap.mdc +6 -0
  92. package/rules/js-run/js/pino.mdc +6 -0
  93. package/rules/js-run/js/project-structure.mdc +11 -0
  94. package/rules/js-run/js/runtime.mdc +14 -0
  95. package/rules/js-run/js/scope.mdc +11 -0
  96. package/rules/js-run/js/settimeout.mdc +11 -0
  97. package/rules/js-run/js/temporal.mdc +5 -0
  98. package/rules/js-run/main.mdc +16 -218
  99. package/rules/k8s/js/configmap.mdc +41 -0
  100. package/rules/k8s/js/deployment_resources.mdc +49 -0
  101. package/rules/k8s/js/hasura_httproute.mdc +91 -0
  102. package/rules/k8s/js/hpa_apiversion.mdc +27 -0
  103. package/rules/k8s/js/ingress_gateway.mdc +16 -0
  104. package/rules/k8s/js/kustomize_structure.mdc +144 -0
  105. package/rules/k8s/js/lint_k8s.mdc +72 -0
  106. package/rules/k8s/js/multidoc_yaml.mdc +5 -0
  107. package/rules/k8s/js/network_policy.mdc +136 -0
  108. package/rules/k8s/js/schema_modeline.mdc +57 -0
  109. package/rules/k8s/js/service.mdc +44 -0
  110. package/rules/k8s/js/topology_hpa_pdb.mdc +181 -0
  111. package/rules/k8s/main.mdc +30 -843
  112. package/rules/nginx-default-tpl/js/dockerfile.mdc +36 -0
  113. package/rules/nginx-default-tpl/js/http-route.mdc +41 -0
  114. package/rules/nginx-default-tpl/js/ini-keys.mdc +21 -0
  115. package/rules/nginx-default-tpl/js/template-structure.mdc +86 -0
  116. package/rules/nginx-default-tpl/js/vscode.mdc +37 -0
  117. package/rules/nginx-default-tpl/main.mdc +6 -112
  118. package/rules/npm-module/js/docs/index.md +5 -5
  119. package/rules/npm-module/js/docs/rule_meta.md +6 -6
  120. package/rules/npm-module/js/docs/skill_meta.md +8 -8
  121. package/rules/npm-module/js/header_doc_pointer.mdc +18 -0
  122. package/rules/npm-module/js/package_structure.mdc +62 -0
  123. package/rules/npm-module/js/rule_meta.mdc +11 -0
  124. package/rules/npm-module/js/skill_meta.mdc +11 -0
  125. package/rules/npm-module/main.mdc +10 -55
  126. package/rules/php/js/lint_php_yml.mdc +12 -0
  127. package/rules/php/js/tooling.mdc +66 -0
  128. package/rules/php/main.mdc +7 -66
  129. package/rules/python/js/lint_python_yml.mdc +23 -0
  130. package/rules/python/js/pyproject_toml.mdc +32 -0
  131. package/rules/python/js/tooling.mdc +23 -0
  132. package/rules/python/main.mdc +9 -33
  133. package/rules/rego/js/rego-lint.mdc +31 -0
  134. package/rules/rego/js/vscode_extensions.mdc +11 -0
  135. package/rules/rego/js/vscode_settings.mdc +13 -0
  136. package/rules/rego/main.mdc +8 -24
  137. package/rules/rust/js/coverage.mdc +28 -0
  138. package/rules/rust/js/lint.mdc +22 -0
  139. package/rules/rust/js/tauri_composition.mdc +8 -0
  140. package/rules/rust/js/vscode_extensions.mdc +12 -0
  141. package/rules/rust/main.mdc +8 -38
  142. package/rules/security/js/rego_policies.mdc +15 -0
  143. package/rules/security/js/sample_secret.mdc +19 -0
  144. package/rules/security/js/trufflehog.mdc +21 -0
  145. package/rules/security/main.mdc +7 -35
  146. package/rules/style/js/admin-table.mdc +88 -0
  147. package/rules/style/js/colors.mdc +21 -0
  148. package/rules/style/js/gap.mdc +22 -0
  149. package/rules/style/js/quasar-fixes.mdc +32 -0
  150. package/rules/style/js/quasar.mdc +7 -0
  151. package/rules/style/js/tooling.mdc +85 -0
  152. package/rules/style/main.mdc +13 -253
  153. package/rules/tauri/js/cargo_mutants_config.mdc +39 -0
  154. package/rules/tauri/js/tool_surface.mdc +21 -0
  155. package/rules/tauri/js/tooling.mdc +25 -0
  156. package/rules/tauri/main.mdc +8 -78
  157. package/rules/test/js/cargo_mutants_config.mdc +18 -0
  158. package/rules/test/js/docs/index.md +7 -7
  159. package/rules/test/js/location.mdc +52 -0
  160. package/rules/test/js/no-console-store-restore.mdc +11 -0
  161. package/rules/test/js/no-process-chdir.mdc +15 -0
  162. package/rules/test/js/no-relative-fs-path.mdc +22 -0
  163. package/rules/test/js/sandbox-aware-test.mdc +28 -0
  164. package/rules/test/js/stryker_config.mdc +26 -0
  165. package/rules/test/js/vitest-config-pool-forks.mdc +33 -0
  166. package/rules/test/main.mdc +18 -184
  167. package/rules/text/js/ci-lint-text.mdc +15 -0
  168. package/rules/text/js/cspell.mdc +81 -0
  169. package/rules/text/js/dotenv-linter.mdc +16 -0
  170. package/rules/text/js/forbidden-prettier.mdc +13 -0
  171. package/rules/text/js/markdownlint.mdc +25 -0
  172. package/rules/text/js/oxfmt.mdc +35 -0
  173. package/rules/text/js/package-json.mdc +26 -0
  174. package/rules/text/js/shellcheck.mdc +18 -0
  175. package/rules/text/js/v8r.mdc +23 -0
  176. package/rules/text/js/vscode.mdc +86 -0
  177. package/rules/text/main.mdc +20 -237
  178. package/rules/vue/js/composition-api.mdc +82 -0
  179. package/rules/vue/js/nheader-layout.mdc +171 -0
  180. package/rules/vue/js/node-imports.mdc +25 -0
  181. package/rules/vue/js/quasar-ui.mdc +32 -0
  182. package/rules/vue/js/structure.mdc +101 -0
  183. package/rules/vue/js/testing.mdc +32 -0
  184. package/rules/vue/js/tfm-translations.mdc +26 -0
  185. package/rules/vue/js/vite-config.mdc +126 -0
  186. package/rules/vue/js/vite-env.mdc +55 -0
  187. package/rules/vue/js/vue-imports.mdc +25 -0
  188. package/rules/vue/main.mdc +16 -640
  189. package/scripts/auto-rules.mjs +6 -6
  190. package/scripts/auto-skills.mjs +3 -3
  191. package/scripts/docs/auto-rules.md +17 -31
  192. package/scripts/docs/auto-skills.md +18 -163
  193. package/scripts/docs/index.md +16 -16
  194. package/scripts/lib/docs/index.md +36 -36
  195. package/scripts/lib/docs/mirror-parity.md +7 -7
  196. package/scripts/lib/docs/rule-meta.md +12 -12
  197. package/scripts/lib/docs/skill-meta.md +9 -9
  198. package/scripts/lib/docs/worktree-notice.md +10 -8
  199. package/scripts/lib/rule-meta.mjs +6 -6
  200. package/scripts/lib/skill-meta.mjs +6 -6
  201. package/scripts/lib/worktree-notice.mjs +2 -2
  202. package/scripts/utils/docs/index.md +14 -14
@@ -4,253 +4,36 @@ alwaysApply: true
4
4
  version: '1.30'
5
5
  ---
6
6
 
7
- **oxfmt** (`.oxfmtrc.json`, редактор), **cspell**, **shellcheck** (tracked `*.sh` у `lint-text`), **[dotenv-linter](https://dotenv-linter.github.io/)** (`.env*` у `lint-text`), **markdownlint-cli2**, **[v8r](https://chris48s.github.io/v8r/)** ([Schema Store](https://www.schemastore.org/)), розширення **DavidAnson.vscode-markdownlint** / **timonwong.shellcheck**, workflow **`lint-text`**.
7
+ Правило охоплює весь текстовий стек проєкту: форматування (oxfmt), перевірку правопису (cspell), shell-скрипти (shellcheck), `.env`-файли (dotenv-linter), Markdown (markdownlint-cli2), JSON/YAML/TOML-схеми (v8r) та CI-workflow.
8
8
 
9
- ```json title=".vscode/extensions.json"
10
- {
11
- "recommendations": [
12
- "dbaeumer.vscode-eslint",
13
- "github.vscode-github-actions",
14
- "oxc.oxc-vscode",
15
- "DavidAnson.vscode-markdownlint",
16
- "timonwong.shellcheck",
17
- "redhat.vscode-yaml",
18
- "irongeek.vscode-env"
19
- ]
20
- }
21
- ```
9
+ [text-vscode](./js/vscode.mdc)
22
10
 
23
- Канон `recommendations` (substring requirement): [extensions.json.snippet.json](./policy/vscode_extensions/template/extensions.json.snippet.json)
11
+ [text-oxfmt](./js/oxfmt.mdc)
24
12
 
25
- ```json title=".vscode/settings.json"
26
- {
27
- "files.associations": {
28
- "*.env.*": "env",
29
- "*.env": "env"
30
- },
31
- "editor.formatOnSave": true,
32
- "[css]": {
33
- "editor.defaultFormatter": "oxc.oxc-vscode"
34
- },
35
- "[graphql]": {
36
- "editor.defaultFormatter": "oxc.oxc-vscode"
37
- },
38
- "[handlebars]": {
39
- "editor.defaultFormatter": "oxc.oxc-vscode"
40
- },
41
- "[html]": {
42
- "editor.defaultFormatter": "oxc.oxc-vscode"
43
- },
44
- "[javascript]": {
45
- "editor.defaultFormatter": "oxc.oxc-vscode"
46
- },
47
- "[json]": {
48
- "editor.defaultFormatter": "oxc.oxc-vscode"
49
- },
50
- "[json5]": {
51
- "editor.defaultFormatter": "oxc.oxc-vscode"
52
- },
53
- "[jsonc]": {
54
- "editor.defaultFormatter": "oxc.oxc-vscode"
55
- },
56
- "[less]": {
57
- "editor.defaultFormatter": "oxc.oxc-vscode"
58
- },
59
- "[markdown]": {
60
- "editor.defaultFormatter": "oxc.oxc-vscode"
61
- },
62
- "[mdx]": {
63
- "editor.defaultFormatter": "oxc.oxc-vscode"
64
- },
65
- "[scss]": {
66
- "editor.defaultFormatter": "oxc.oxc-vscode"
67
- },
68
- "[toml]": {
69
- "editor.defaultFormatter": "oxc.oxc-vscode"
70
- },
71
- "[typescript]": {
72
- "editor.defaultFormatter": "oxc.oxc-vscode"
73
- },
74
- "[vue]": {
75
- "editor.defaultFormatter": "oxc.oxc-vscode"
76
- },
77
- "[yaml]": {
78
- "editor.defaultFormatter": "oxc.oxc-vscode"
79
- },
80
- "oxc.path.oxfmt": "/opt/homebrew/bin/oxfmt"
81
- }
82
- ```
13
+ [text-forbidden-prettier](./js/forbidden-prettier.mdc)
83
14
 
84
- Канон `editor.formatOnSave` + `editor.defaultFormatter` для основних мов: [settings.json.snippet.json](./policy/vscode_settings/template/settings.json.snippet.json)
15
+ [text-cspell](./js/cspell.mdc)
85
16
 
86
- У корені проєкту має бути файл з правилами форматування для **oxfmt**:
17
+ [text-markdownlint](./js/markdownlint.mdc)
87
18
 
88
- ```json title=".oxfmtrc.json"
89
- {
90
- "ignorePatterns": ["**/hasura/metadata/**", "**/schema.graphql", "**/auto-imports.d.ts"],
91
- "arrowParens": "avoid",
92
- "printWidth": 120,
93
- "bracketSpacing": true,
94
- "bracketSameLine": true,
95
- "embeddedLanguageFormatting": "auto",
96
- "endOfLine": "lf",
97
- "htmlWhitespaceSensitivity": "css",
98
- "insertPragma": false,
99
- "jsxSingleQuote": true,
100
- "proseWrap": "preserve",
101
- "quoteProps": "as-needed",
102
- "requirePragma": false,
103
- "semi": false,
104
- "singleQuote": true,
105
- "tabWidth": 2,
106
- "trailingComma": "none",
107
- "useTabs": false,
108
- "vueIndentScriptAndStyle": false
109
- }
110
- ```
19
+ [text-shellcheck](./js/shellcheck.mdc)
111
20
 
112
- Канон мінімального набору ключів і `ignorePatterns`: [.oxfmtrc.json.snippet.json](./policy/oxfmtrc/template/.oxfmtrc.json.snippet.json)
21
+ [text-dotenv-linter](./js/dotenv-linter.mdc)
113
22
 
114
- Поле **`ignorePatterns`** обовʼязкове: у масиві мають бути **`**/hasura/metadata/**`**, **`**/schema.graphql`** і **`**/auto-imports.d.ts`**; інші glob-и додавай за потреби (згенеровані каталоги тощо) — канон задає мінімум, локальні розширення дозволені.
23
+ [text-v8r](./js/v8r.mdc)
115
24
 
116
- Також потрібно прибрати, якщо є в проєкті, модуль **`@nitra/prettier-config`**, **prettier** та всі виклики prettier і налаштування для нього. Канон заборонених top-level/`dependencies`/`devDependencies` (prettier, `@nitra/prettier-config`, `markdownlint-cli2`): [package.json.deny.json](./policy/package_json/template/package.json.deny.json)
25
+ [text-package-json](./js/package-json.mdc)
117
26
 
118
- Завжди пиши **JSDoc** до функцій та методів.
27
+ [text-ci-lint-text](./js/ci-lint-text.mdc)
119
28
 
120
- **`package.json`:** у `devDependencies` має бути **`@nitra/cspell-dict`** (**`^2.0.0`** або новіший у лінії 2.x) — з **2.0.0** у пакет транзитивно входять типові **`@cspell/dict-*`**, тому **не** додавай їх окремо в корінь. Окремий `package.json`-скрипт `lint-text` не потрібен: запуск іде через **`n-cursor lint text`**. **`markdownlint-cli2`** запускається rule-адаптером через **`bunx markdownlint-cli2`**, не додавай пакет до devDependencies. **`v8r`** лише через **`bunx v8r`**, не в devDependencies. Окремий пакет **`markdownlint`** не потрібний.
29
+ ## Швидкий gate через conftest
121
30
 
122
- **shellcheck:** інструмент лише в **`PATH`** (як у **ga.mdc** для `lint-ga`), **не** додавай до `dependencies` / `devDependencies`. Якщо `shellcheck` відсутній — встанови локально (**macOS:** `brew install shellcheck`; **Debian/Ubuntu:** `sudo apt-get install -y shellcheck`; **Arch:** `sudo pacman -S shellcheck`). Канонічний запуск — **`n-cursor lint text`** (бінарка з `node_modules/.bin/` пакету `@nitra/cursor`): після **`cspell .`** виконується **`runShellcheckText()`** з пакета — циклічно **`shellcheck -f diff`** і **`patch -p1`** для авто-виправлень, потім повний прогін **`shellcheck`** по всіх tracked `*.sh` (у git) або по `**/*.sh` без `node_modules`. Потрібен також **`patch`** у `PATH` (на macOS зазвичай уже є).
31
+ Rego-пакети, що перевіряються через conftest (auto-discovered за `target.json` поряд із `.rego`):
123
32
 
124
- **dotenv-linter:** після shellcheck CLI запускає **`runDotenvLinter()`** з пакета рекурсивно по `.env*`-файлах проєкту через **`dotenv-linter fix -r --no-backup --quiet . --exclude node_modules --exclude .envrc`**, далі такий самий **`check`** для фінальної перевірки. Інструмент має бути в **`PATH`** і **не** додається в `dependencies` / `devDependencies`. Якщо `dotenv-linter` відсутній — встанови локально (**macOS:** `brew install dotenv-linter`; **Linux:** `curl -sSfL https://git.io/JLbXn | sh -s -- -b /usr/local/bin`; через **cargo:** `cargo install dotenv-linter`).
125
-
126
- У v8r **немає** прапорця тихого режиму; rule-адаптер **`n-cursor lint text`** на четвертому кроці викликає **`runV8rWithGlobs()`** з пакета (реалізація `npm/rules/text/js/run-v8r.mjs`): під капотом послідовні **`bunx v8r`** для кожного типу (**json**, **json5**, **yml**, **yaml**, **toml**), бо один процес v8r з кількома глобами падає з **98**, якщо хоч один glob порожній, і тоді інші розширення не перевіряються. Вивід при кодах **0** і **98** не показується. Каталог схем **`schemas/v8r-catalog.json`** пакета `@nitra/cursor` обгортка підставляє в v8r сама.
127
-
128
- ```json title="package.json"
129
- {
130
- "devDependencies": {
131
- "@nitra/cspell-dict": "^2.1.0"
132
- }
133
- }
134
- ```
135
-
136
- **v8r:** без обгортки — чотири виклики `(bunx v8r "<glob>" || [ $? -eq 98 ])` для **`**/*.json`**, **`**/*.yml`**, **`**/*.yaml`**, **`**/*.toml`** (за потреби окремо **json5**). Враховує `.gitignore`. Для **`**/*.json`** опційно додай **власний каталог схем** [`--catalogs`](https://chris48s.github.io/v8r/usage-examples/#using-a-custom-catlog) (наприклад `-c npm/schemas/v8r-catalog.json` у репозиторії пакета `@nitra/cursor` або `-c https://unpkg.com/@nitra/cursor/schemas/v8r-catalog.json`), щоб перевіряти **`.n-cursor.json`** за схемою з [unpkg](https://unpkg.com/@nitra/cursor/schemas/n-cursor.json).
137
-
138
- У корені проєкту має бути **`.v8rignore`**: **v8r** шукає схему в [Schema Store](https://www.schemastore.org/); для JSON без запису там перевірка завершується помилкою. Мінімум виключи **`.vscode/extensions.json`** і **`.vscode/settings.json`** (немає стабільної схеми в каталозі). Інші файли без схеми — за тією ж логікою; не розширюй ignore, щоб приховати проблеми там, де схема є. За потреби додай **`.git/**`** (службові JSON під `.git`) та **`npm/schemas/n-cursor.json`** у репозиторії `@nitra/cursor`, якщо для цього файлу немає стабільної схеми в ланцюжку v8r.
139
-
140
- ```text title=".v8rignore"
141
- .vscode/extensions.json
142
- .vscode/settings.json
143
- .git/**
144
- ```
145
-
146
- ```json title=".markdownlint-cli2.jsonc"
147
- {
148
- "gitignore": true,
149
- "config": {
150
- "default": true,
151
- "MD013": false,
152
- "MD024": {
153
- "siblings_only": true
154
- },
155
- "MD029": false,
156
- "MD040": false,
157
- "MD041": false
158
- }
159
- }
160
- ```
161
-
162
- Канон: [.markdownlint-cli2.jsonc.snippet.jsonc](./policy/markdownlint/template/.markdownlint-cli2.jsonc.snippet.jsonc)
163
-
164
- **MD041** off навмисно (`.mdc` з frontmatter). Деталі — [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2).
165
-
166
- ## Cspell
167
-
168
- У корені проєкту має бути `.cspell.json` і залежності для cspell у кореневому `package.json` (зазвичай `devDependencies`).
169
-
170
- Додай workflow `.github/workflows/lint-text.yml`:
171
-
172
- - Канон: [lint-text.yml.snippet.yml](./policy/lint_text/template/lint-text.yml.snippet.yml)
173
-
174
- Перед **`./.github/actions/setup-bun-deps`** — **`actions/checkout@v6`** (див. **ga.mdc**). Після composite — кроки **`Install shellcheck`** (apt) і **`Install dotenv-linter`** (curl), бо `n-cursor lint text` вимагає обидва бінарники в PATH; на ubuntu-latest shellcheck часто вже є, dotenv-linter — ні. Composite: Node 24, Bun, кеш, `bun install --frozen-lockfile`.
175
-
176
- Не дублюй окремий workflow з тими самими кроками cspell/markdownlint.
177
-
178
- **`.cspell.json`**, `version: "0.2"`, **`language`**, **`import`** з `@nitra/cspell-dict`, **`ignorePaths`**, **`words`** лише для назв/термінів, коли не виправити текстом.
179
-
180
- Базово (англійська + українська + корпоративний словник):
181
-
182
- ```json title=".cspell.json"
183
- {
184
- "version": "0.2",
185
- "language": "nitra",
186
- "ignorePaths": ["**/node_modules/**", "**/vscode-extension/**", "**/.git/**", ".vscode", "report", "*.svg", "**/k8s/**/*.yaml", "docs/adr/**"],
187
- "import": ["@nitra/cspell-dict/cspell-ext.json"],
188
- "words": []
189
- }
190
- ```
191
-
192
- Канон базових ключів `.cspell.json` (`version`, `ignorePaths`): [.cspell.json.snippet.json](./policy/cspell/template/.cspell.json.snippet.json). Обовʼязковий запис у `import`: [.cspell.json.contains.json](./policy/cspell/template/.cspell.json.contains.json). Заборонено імпортувати окремі `@cspell/dict-*` у `.cspell.json`: [.cspell.json.deny.json](./policy/cspell/template/.cspell.json.deny.json).
193
-
194
- `docs/adr/**` у канонічному `ignorePaths` — машинно-генеровані MADR-документи (драфти `capture-decisions.sh` + clean-ADR-и після `normalize-decisions.sh`). cspell-перевірка там безглузда: чернетка стирається наступним прогоном хук-ланцюжка, а будь-яка ручна правка правопису перезаписується. Локальні розширення `ignorePaths` дозволені — це лише мінімум.
195
-
196
- ```json title="package.json"
197
- {
198
- "devDependencies": {
199
- "@nitra/cspell-dict": "^2.1.0"
200
- }
201
- }
202
- ```
203
-
204
- ## Проєкт з українською та російською (і суміжні мови)
205
-
206
- У **`@nitra/cspell-dict`** від **2.0.0** уже зібрані залежності на **`@cspell/dict-uk-ua`**, **`@cspell/dict-ru_ru`** та інші типові словники — **не** дублюй їх у кореневому `package.json` і **не** імпортуй **`@cspell/dict-*/cspell-ext.json`** у `.cspell.json`.
207
-
208
- **1. Залежності** — лише корпоративний пакет:
209
-
210
- ```json title="package.json"
211
- {
212
- "devDependencies": {
213
- "@nitra/cspell-dict": "^2.1.0"
214
- }
215
- }
216
- ```
217
-
218
- Встановлення: `bun add -d @nitra/cspell-dict@^2.0.0`.
219
-
220
- **2. `.cspell.json`** — у полі **`language`** додай потрібні коди (наприклад **`uk`**, **`ru-ru`** разом з **`en`** та **`nitra`**). У **`import`** залиш лише **`@nitra/cspell-dict/cspell-ext.json`**:
221
-
222
- ```json title=".cspell.json"
223
- {
224
- "version": "0.2",
225
- "language": "en,uk,ru-ru,nitra",
226
- "ignorePaths": ["**/node_modules/**", "**/vscode-extension/**", "**/.git/**", ".vscode", "report", "*.svg", "**/k8s/**/*.yaml", "docs/adr/**"],
227
- "import": ["@nitra/cspell-dict/cspell-ext.json"],
228
- "words": []
229
- }
230
- ```
231
-
232
- Підлаштуй **`language`** під проєкт. Порядок у **`import`** може впливати на пріоритет словників — тримай корпоративний **`@nitra/cspell-dict`** першим, якщо додаєш інші розширення (рідко).
233
-
234
- **Український апостроф:** у словах не використовуй прямий символ `'` (U+0027); потрібен типографський апостроф `’` (U+2019). Якщо після цього cspell досі підсвічує слово як невідоме — додай його до масиву `words` у `.cspell.json`.
235
-
236
- ## Локальні виключення (cspell `words`)
237
-
238
- Коли **cspell** підсвічує слово, спочатку **виправ текст**, а не розширюй словник:
239
-
240
- - виправ **друкарські помилки** та неправильні форми;
241
- - **перефразуй коректною українською** (або англійською, залежно від контексту файлу): заміни кальки й випадкові склади на звичні формулювання зі словників;
242
- - заміни **жаргон**, якщо є природний еквівалент у тому ж стилі документації (наприклад, у коментарях пиши «функція зворотного виклику» замість розмовного запозичення з англійського `callback`).
243
-
244
- У секцію `words` у `.cspell.json` додавай записи **лише якщо переписати коректно неможливо** або **недоречно**: власні назви, стабільні технічні терміни без усталеного перекладу в проєкті, ідентифікатори зовнішніх API тощо.
245
-
246
- ## Інші мови
247
-
248
- Якщо потрібна мова вже є в залежностях **`@nitra/cspell-dict`** — додай лише код у **`language`**, без окремих **`@cspell/dict-*`** у споживачі. Якщо мови немає в корпоративному пакеті — розширюй **`@nitra/cspell-dict`**, а не підключай **`@cspell/dict-*`** у корені репозиторію-споживача. Огляд upstream-словників: [streetsidesoftware/cspell-dicts](https://github.com/streetsidesoftware/cspell-dicts).
249
-
250
- ## Найменування каталогів
251
-
252
- kebab-case
253
-
254
- ## Перевірка
255
-
256
- `npx @nitra/cursor fix text` (охоплює oxfmt, cspell, shellcheck, markdownlint, v8r і CI для `n-cursor lint text`). Зокрема падає, якщо у корені є `.prettierignore`, `.prettierrc*`, `prettier.config.*` або у `package.json#scripts` зустрічається команда з `prettier` — Prettier повністю заборонено, форматування лише через **oxfmt**.
33
+ - `text.cspell` — `.cspell.json`: version, ignorePaths, import (@nitra/cspell-dict), language, заборонені @cspell/dict-* у import
34
+ - `text.lint_text` — `.github/workflows/lint-text.yml`: name, on.push/pull_request branches+paths, runs-on, permissions, кроки uses+run
35
+ - `text.markdownlint``.markdownlint-cli2.jsonc`: gitignore, config leafs (MD013, MD024.siblings_only, MD029, MD040, MD041)
36
+ - `text.oxfmtrc` — `.oxfmtrc.json`: обовʼязкові ключі (presence), ignorePatterns subset, scalar leafs
37
+ - `text.package_json` — `package.json`: заборонені top-level/deps (prettier, @nitra/prettier-config, markdownlint-cli2), @nitra/cspell-dict ^2.0.0+ у devDependencies, scripts без prettier
38
+ - `text.vscode_extensions` — `.vscode/extensions.json`: recommendations містить канонічні розширення
39
+ - `text.vscode_settings` — `.vscode/settings.json`: editor.formatOnSave, editor.defaultFormatter для мов
@@ -0,0 +1,82 @@
1
+ ## Найкращі практики Vue 3 Composition API
2
+
3
+ ```javascript
4
+ const vue3CompositionApiBestPractices = [
5
+ 'Використовуй функцію setup() для логіки компонента',
6
+ 'Реалізуй computed змінні через $computed()',
7
+ 'Реалізуй ref змінні через $ref',
8
+ 'Використовуй watch і watchEffect для побічних ефектів',
9
+ 'Підключай lifecycle hooks: onMounted, onUpdated тощо',
10
+ 'Для глибоко вкладених залежностей використовуй composables, props/emits або store'
11
+ 'не використовуй provide/inject для залежностей'
12
+ ]
13
+ ```
14
+
15
+ ### Патерни та антипатерни
16
+
17
+ - Для глибоко вкладених залежностей використовуй **composables**, **props/emits** або **store**; **renderless**-компоненти / **slots** — коли логіку відділяєш від розмітки.
18
+ - **HTTP:** окремі модулі **services** або **composables** для API; **async/await**.
19
+ - **Події:** батько–дитина через **emits**; для не пов'язаних гілок — **store**.
20
+ - Не мутуй **props** напряму — оновлення через подію вгору або v-model.
21
+ - Обмежуй зайве в глобальному стані; локальний стан у компоненті — за замовчуванням.
22
+ - Уникай прямої роботи з **DOM**, якщо достатньо реактивного шаблону та ref.
23
+
24
+ ### State management
25
+
26
+ - **Single source of truth** для спільних даних: у нових проєктах на Vue 3 **Pinia** (модульні stores, actions).
27
+ - Похідний стан — через обчислення в store або **computed** у компонентах, без «тихих» побічних ефектів у getters.
28
+
29
+ ### Обробка помилок
30
+
31
+ - **try/catch** навколо async-операцій; зрозумілі повідомлення для користувача через notifySuccess, notifyError; логування на сервіс моніторингу за потреби.
32
+
33
+ ### Продуктивність
34
+
35
+ - **v-for** — стабільні унікальні **`:key`**; не плутай **v-if** (умовний mount) і **v-show** (перемикання visibility).
36
+ - **debounce/throttle** для частих подій.
37
+ - Після ручних **addEventListener** / підписок — прибирай у **onUnmounted**.
38
+
39
+ ### Функції в шаблоні
40
+
41
+ Виклики функцій у шаблоні дозволені **лише** в обробниках подій (`@click`, `@change` тощо). У всіх інших місцях — `v-if`, `v-show`, атрибутах (`:prop`), інтерполяціях (`{{ }}`) — замінюй функції на `computed`-властивості: функція виконується при **кожному** render-і, тоді як `computed` кешується і перераховується лише при зміні залежностей.
42
+
43
+ ```vue
44
+ <!-- ❌ функція в умові, атрибуті та інтерполяції -->
45
+ <q-item v-if="getItems(order).length" :label="getLabel(item)">
46
+ {{ formatName(user) }}
47
+ </q-item>
48
+
49
+ <!-- ✅ реактивні змінні / computed / props -->
50
+ <q-item v-if="itemsMap[order.id].length" :label="item.label">
51
+ {{ user.displayName }}
52
+ </q-item>
53
+ <!-- обробник події — виклик функції дозволений -->
54
+ <q-btn @click="doSomething(item)" />
55
+ ```
56
+
57
+ ### Безпека
58
+
59
+ - Не довіряй **v-html** без санітизації; для форм/API — **CSRF**-захист за потреби; валідація **на сервері** обов'язкова.
60
+
61
+ ### Приклад компонента
62
+
63
+ ```javascript
64
+ // Приклад Vue 3 компонента з Composition API
65
+ import { computed, onMounted } from 'vue'
66
+
67
+ export default {
68
+ setup() {
69
+ const count = $ref(0)
70
+ const doubleCount = $computed(() => count * 2)
71
+
72
+ onMounted(() => {
73
+ console.log('Компонент змонтовано')
74
+ })
75
+
76
+ return {
77
+ count,
78
+ doubleCount
79
+ }
80
+ }
81
+ }
82
+ ```
@@ -0,0 +1,171 @@
1
+ ## NHeader — телепорт-слоти на сторінках
2
+
3
+ У проектах з `NHeader` використовуй `<teleport>` для вбудовування контенту сторінки в шапку:
4
+
5
+ | Слот | Призначення |
6
+ | --- | --- |
7
+ | `#header-subtitle` | Заголовок сторінки (якщо потрібно перевизначити subtitle) |
8
+ | `#header-center` | Важливі повідомлення та елементи управління |
9
+ | `#header-filters` | Фільтри, кнопки та інші елементи управління сторінки |
10
+
11
+ Оскільки `NHeader` за замовчуванням темний, додавай до полів і селектів у телепортах: `dark`, `standout="bg-white text-primary"`, `:options-dark="false"`.
12
+
13
+ Завжди обгортай `<teleport>` в `v-if="mounted"` (де `mounted` — `$ref(false)`, що встановлюється в `onMounted`), щоб уникнути помилки відсутності target-елемента при SSR / першому рендері.
14
+
15
+ ```vue
16
+ <template>
17
+ <q-page>
18
+ <!-- ФІЛЬТРИ В ШАПЦІ -->
19
+ <teleport v-if="mounted" to="#header-filters">
20
+ <div class="col row items-center n-gap-sm q-pa-sm">
21
+ <q-input
22
+ v-model="pageStore.filterName"
23
+ :label="t`Поиск по названию`"
24
+ debounce="200"
25
+ standout="bg-white text-primary"
26
+ clearable
27
+ dense
28
+ dark
29
+ class="col"
30
+ style="min-width: 120px">
31
+ <template #prepend>
32
+ <q-icon name="search" />
33
+ </template>
34
+ </q-input>
35
+
36
+ <n-select-multi
37
+ v-model="pageStore.filterRequestTypes"
38
+ :options="requestTypeOptions"
39
+ :label="t`Тип запроса`"
40
+ dark
41
+ standout="bg-white text-primary"
42
+ :options-dark="false"
43
+ style="min-width: 180px; max-width: 400px"
44
+ dense
45
+ emit-value
46
+ map-options
47
+ clearable
48
+ searchable
49
+ :stack-label="false" />
50
+
51
+ <q-btn
52
+ @click="addItem"
53
+ icon="add"
54
+ :label="t`Добавить`"
55
+ color="primary"
56
+ no-caps
57
+ padding="8px 12px"
58
+ unelevated />
59
+ </div>
60
+ </teleport>
61
+
62
+ <!-- ОСНОВНИЙ КОНТЕНТ -->
63
+ ...
64
+ </q-page>
65
+ </template>
66
+ <script setup>
67
+ const mounted = $ref(false)
68
+ onMounted(() => { mounted = true })
69
+ </script>
70
+ ```
71
+
72
+ ## Layout з NHeader
73
+
74
+ Для нових layout-ів використовуй `NHeader` з вбудованими `NLang` і `NMenu`.
75
+
76
+ ```vue
77
+ <template>
78
+ <q-layout view="hHh Lpr lFf">
79
+ <n-header
80
+ v-model="leftSideOpened"
81
+ :logo="baseUrl + 'logo.png'"
82
+ :logo-url="homeUrl"
83
+ title="My App"
84
+ :subtitle="subtitle"
85
+ :username="userName"
86
+ toolbar-dark>
87
+ <template #top-toolbar>
88
+ <div class="platform-ios-only q-py-lg" />
89
+ </template>
90
+ <div>default slot content</div>
91
+ </n-header>
92
+
93
+ <!-- ЛЕВАЯ КОЛОНКА -->
94
+ <q-drawer v-model="leftSideOpened" :breakpoint="700" :width="300" overlay class="col column shadow-5 bg-grey-1">
95
+ <div class="platform-ios-only q-py-lg" />
96
+ <div v-if="!$q.screen.gt.xs" class="q-pa-sm row items-center">
97
+ <q-icon name="account_circle" color="primary" size="32px" class="q-mr-sm" />
98
+ <div class="text-subtitle1">{{ user.name }}</div>
99
+ </div>
100
+ <n-menu v-model="activeMenu" :menu="menu" />
101
+ <q-space />
102
+ <n-menu :menu="homeMenu" />
103
+ <div class="platform-ios-only q-py-md" />
104
+ </q-drawer>
105
+
106
+ <q-page-container>
107
+ <router-view />
108
+ </q-page-container>
109
+ </q-layout>
110
+ </template>
111
+ <script setup>
112
+ import { lang, tf as tfm } from '@nitra/tfm'
113
+ const t = tfm.bind({ tr: getTr() })
114
+
115
+ const baseUrl = import.meta.env.BASE_URL
116
+ const homeUrl = String.raw`https:\\` + import.meta.env.VITE_DOMAIN
117
+
118
+ // Ліва колонка
119
+ const leftSideOpened = $ref(false)
120
+ const activeMenu = $ref(null)
121
+
122
+ // Заголовок у шапці з поточного пункту меню
123
+ const subtitle = computed(() => (activeMenu ? getTr()[activeMenu.labelKey]?.[lang.value] || activeMenu?.labelKey : ''))
124
+
125
+ // Меню
126
+ const menu = computed(() =>
127
+ [
128
+ {
129
+ icon: 'sym_o_store',
130
+ label: t`Клиенты`,
131
+ labelKey: t`Клиенты`,
132
+ routeName: 'customer'
133
+ },
134
+ {
135
+ icon: 'sym_o_route',
136
+ label: t`Маршруты и визиты`,
137
+ items: [
138
+ {
139
+ icon: 'sym_o_route',
140
+ label: t`Маршруты`,
141
+ labelKey: t`Маршруты`,
142
+ routeName: 'route'
143
+ },
144
+ {
145
+ icon: 'sym_o_event_upcoming',
146
+ label: t`Переносы маршрутов`,
147
+ labelKey: t`Переносы маршрутов`,
148
+ routeName: 'route_postpone'
149
+ }
150
+ ]
151
+ }
152
+ ].filter(item => {
153
+ if (item.items?.length) {
154
+ item.items = item.items.filter(i => can[i.permissionRoute || i.routeName])
155
+ return item.items.length > 0
156
+ }
157
+ return can[item.routeName]
158
+ })
159
+ )
160
+
161
+ /**
162
+ * LOCALIZATION
163
+ * @returns {object} translations
164
+ */
165
+ function getTr() {
166
+ return {
167
+ Клиенты: { en: 'Customers', ro: 'Clienți', tr: 'Müşteriler' }
168
+ }
169
+ }
170
+ </script>
171
+ ```
@@ -0,0 +1,25 @@
1
+ ## Заборонено імпортувати Node-нативні модулі у `.vue` SFC
2
+
3
+ Vue SFC виконується у браузері, тож API Node.js там недоступне. У `<script>` (включно з `<script setup>`)
4
+ заборонено будь-які імпорти вбудованих модулів Node — як з префіксом `node:`, так і bare-ім'ям модуля
5
+ (включно з підшляхами):
6
+
7
+ ```vue title="погано — ламає білд"
8
+ <script setup lang="ts">
9
+ import { setTimeout as sleep } from 'node:timers/promises'
10
+ import fs from 'fs'
11
+ import { readFile } from 'fs/promises'
12
+ import path from 'node:path'
13
+ </script>
14
+ ```
15
+
16
+ Якщо потрібна логіка з Node API — винеси її у server-side утіліту (наприклад, у backend-пакет монорепо)
17
+ та звертайся до неї через HTTP/GraphQL. Браузерні замінники (`window.crypto`, `URL`, `setTimeout` глобальний,
18
+ `AbortController` тощо) використовуй напряму, без import.
19
+
20
+ Правило стосується саме `.vue` файлів. Допоміжні `.ts`/`.js` модулі, які споживаються лише server-side
21
+ (наприклад, окремий пакет утіліт), можуть імпортувати Node-built-ins без обмежень.
22
+
23
+ Перевірка реалізована у `npm/rules/vue/lib/vue-forbidden-imports.mjs` через функцію
24
+ `findForbiddenNodeImportsInVueFile` — аналізує лише `<script>` блоки SFC через **oxc-parser**,
25
+ ігноруючи `<template>`.
@@ -0,0 +1,32 @@
1
+ ## Quasar як UI-основа
2
+
3
+ У Vue-проектах використовуй **Quasar** як базовий UI-фреймворк:
4
+
5
+ - **Компоненти:** `q-btn`, `q-input`, `q-select`, `q-table`, `q-dialog`, `q-card`, `q-layout`, `q-page`, `q-drawer` тощо — основа UI.
6
+ - **Плагіни:** `Notify`, `Dialog`, `Loading` та інші Quasar-плагіни.
7
+ - **Кольори:** використовуй Quasar CSS-змінні (`primary`, `secondary`, `accent`, `positive`, `negative`, `warning`, `info`, `dark`) і утиліти (`text-primary`, `bg-accent` тощо).
8
+ - **Утиліти:** flex-layout (`row`, `col`, `items-center`), spacing (`q-pa-md`, `q-mt-sm`), shadow (`shadow-2`) — зі стандартної бібліотеки Quasar.
9
+ - **Кастомні компоненти** `@nitra/components` — **надбудова** над Quasar, а не заміна; їх слід надавати перевагу лише там, де вони є.
10
+
11
+ ## @nitra/components — надавай перевагу перед Quasar-компонентами
12
+
13
+ При створенні нової функціональності використовуй компоненти `@nitra/components`, якщо логіка компонента дозволяє отримати потрібний функціонал. Заміни:
14
+
15
+ | Завдання | `@nitra/components` | Замість Quasar |
16
+ | --- | --- | --- |
17
+ | Діалоги | `NDialog` | `q-dialog` |
18
+ | Multi-вибір | `NSelectMulti` | `q-select` (multiple) |
19
+ | Текстовий редактор | `NEditor` | `q-editor` |
20
+ | Вибір дати | `NDate` | — |
21
+ | Вибір місяця/року | `NDateMonthYear` | — |
22
+ | Діапазон дат | `NDateRange` | — |
23
+ | Дата і час | `NDateTime` | — |
24
+ | Drag&drop список | `NDraggableList` | — |
25
+ | Редаговане значення | `NEditableString` | — |
26
+ | Повідомлення | `NCallout` | — |
27
+ | Хедер проекту | `NHeader` | — |
28
+ | Перемикання мов | `NLang` | — (якщо `NHeader` не використовується) |
29
+ | Меню проекту | `NMenu` | — |
30
+ | Зображення (масив / одиночне) | `NImages` | — |
31
+ | Завантаження файлів | `NUploader` | — |
32
+ | Вибір колонок `q-table` | `NTableColumns` | — |