@nitra/cursor 12.8.6 → 12.8.8

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 (263) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +1 -1
  3. package/rules/abie/main.mdc +9 -5
  4. package/rules/abie/policy/base_deployment_preem/base_deployment_preem.mdc +22 -0
  5. package/rules/abie/policy/clean_merged_ignore_branches/clean_merged_ignore_branches.mdc +19 -0
  6. package/rules/abie/policy/health_check_policy/health_check_policy.mdc +17 -0
  7. package/rules/abie/policy/http_route_base/http_route_base.mdc +9 -0
  8. package/rules/abie/policy/package_json_shared/package_json_shared.mdc +17 -0
  9. package/rules/adr/js/hooks.mdc +32 -0
  10. package/rules/adr/js/madr_format.mdc +96 -0
  11. package/rules/adr/js/settings_policy.mdc +34 -0
  12. package/rules/adr/main.mdc +17 -95
  13. package/rules/adr/policy/settings_json/settings_json.mdc +7 -0
  14. package/rules/adr/policy/settings_local_json/settings_local_json.mdc +7 -0
  15. package/rules/bun/js/bunfig.mdc +12 -0
  16. package/rules/bun/js/layout.mdc +60 -0
  17. package/rules/bun/js/lint.mdc +9 -0
  18. package/rules/bun/js/package_json.mdc +19 -0
  19. package/rules/bun/main.mdc +7 -60
  20. package/rules/bun/policy/bunfig/bunfig.mdc +12 -0
  21. package/rules/bun/policy/package_json/package_json.mdc +14 -0
  22. package/rules/capacitor/js/ios_spm.mdc +69 -0
  23. package/rules/capacitor/js/version.mdc +29 -0
  24. package/rules/capacitor/main.mdc +6 -22
  25. package/rules/capacitor/policy/package_json/package_json.mdc +9 -0
  26. package/rules/changelog/js/agent-workflow.mdc +15 -0
  27. package/rules/changelog/js/changelog-format.mdc +33 -0
  28. package/rules/changelog/js/comparison-models.mdc +40 -0
  29. package/rules/changelog/main.mdc +4 -98
  30. package/rules/ci4/js/marksman_config.mdc +31 -0
  31. package/rules/ci4/js/vscode_extensions.mdc +33 -0
  32. package/rules/ci4/main.mdc +16 -14
  33. package/rules/ci4/policy/vscode_extensions/vscode_extensions.mdc +9 -0
  34. package/rules/docker/js/compile.mdc +44 -0
  35. package/rules/docker/js/hadolint.mdc +50 -0
  36. package/rules/docker/js/mirror.mdc +13 -0
  37. package/rules/docker/js/multistage.mdc +13 -0
  38. package/rules/docker/js/native-addon.mdc +43 -0
  39. package/rules/docker/js/nginx-tag.mdc +7 -0
  40. package/rules/docker/js/nginx-user.mdc +37 -0
  41. package/rules/docker/js/non-root.mdc +39 -0
  42. package/rules/docker/main.mdc +13 -196
  43. package/rules/docker/policy/lint_docker_yml/lint_docker_yml.mdc +14 -0
  44. package/rules/efes/main.mdc +1 -1
  45. package/rules/efes/policy/package_json_shared/package_json_shared.mdc +30 -0
  46. package/rules/ga/js/lint_toolchain.mdc +15 -0
  47. package/rules/ga/js/required_workflows.mdc +35 -0
  48. package/rules/ga/js/vscode.mdc +17 -0
  49. package/rules/ga/js/workflow_common.mdc +108 -0
  50. package/rules/ga/js/workflows.mdc +32 -0
  51. package/rules/ga/js/zizmor.mdc +7 -0
  52. package/rules/ga/main.mdc +16 -119
  53. package/rules/ga/policy/clean_ga_workflows/clean_ga_workflows.mdc +18 -0
  54. package/rules/ga/policy/clean_merged_branch/clean_merged_branch.mdc +22 -0
  55. package/rules/ga/policy/git_ai/git_ai.mdc +19 -0
  56. package/rules/ga/policy/lint_ga/lint_ga.mdc +21 -0
  57. package/rules/ga/policy/vscode_extensions/vscode_extensions.mdc +9 -0
  58. package/rules/ga/policy/vscode_settings/vscode_settings.mdc +9 -0
  59. package/rules/ga/policy/workflow_common/workflow_common.mdc +18 -0
  60. package/rules/ga/policy/zizmor_yml/zizmor_yml.mdc +9 -0
  61. package/rules/graphql/js/tooling.mdc +13 -0
  62. package/rules/graphql/js/vscode_extensions.mdc +13 -0
  63. package/rules/graphql/main.mdc +4 -21
  64. package/rules/graphql/policy/vscode_extensions/vscode_extensions.mdc +9 -0
  65. package/rules/hasura/js/internal_urls.mdc +27 -0
  66. package/rules/hasura/js/migrations.mdc +13 -0
  67. package/rules/hasura/js/svc_hl.mdc +17 -0
  68. package/rules/hasura/main.mdc +6 -30
  69. package/rules/hasura/policy/svc_hl/svc_hl.mdc +15 -0
  70. package/rules/image-avif/js/avif_generation.mdc +26 -0
  71. package/rules/image-avif/js/package_json_optout.mdc +21 -0
  72. package/rules/image-avif/main.mdc +5 -34
  73. package/rules/image-avif/policy/package_json/package_json.mdc +18 -0
  74. package/rules/image-compress/js/package_json.mdc +7 -0
  75. package/rules/image-compress/js/package_setup.mdc +13 -0
  76. package/rules/image-compress/main.mdc +4 -12
  77. package/rules/image-compress/policy/package_json/package_json.mdc +13 -0
  78. package/rules/js/docs/index.md +3 -3
  79. package/rules/js/js/dep-policy.mdc +17 -0
  80. package/rules/js/js/eslint-config.mdc +28 -0
  81. package/rules/js/js/extensions.mdc +8 -0
  82. package/rules/js/js/file-extensions.mdc +12 -0
  83. package/rules/js/js/for-in.mdc +26 -0
  84. package/rules/js/js/jscpd.mdc +42 -0
  85. package/rules/js/js/knip.mdc +15 -0
  86. package/rules/js/js/lint-js-workflow.mdc +58 -0
  87. package/rules/js/js/oxlintrc.mdc +20 -0
  88. package/rules/js/js/package-json.mdc +31 -0
  89. package/rules/js/js/tests.mdc +9 -0
  90. package/rules/js/js/utils-lib-structure.mdc +15 -0
  91. package/rules/js/main.mdc +19 -211
  92. package/rules/js/policy/jscpd/jscpd.mdc +14 -0
  93. package/rules/js/policy/lint_js_yml/lint_js_yml.mdc +14 -0
  94. package/rules/js/policy/package_json/package_json.mdc +15 -0
  95. package/rules/js/policy/vscode_extensions/vscode_extensions.mdc +11 -0
  96. package/rules/js-bun-db/js/bun-sql-migration.mdc +15 -0
  97. package/rules/js-bun-db/js/connection.mdc +42 -0
  98. package/rules/js-bun-db/js/pg-format-identifiers.mdc +102 -0
  99. package/rules/js-bun-db/js/pg-format-shim.mdc +99 -0
  100. package/rules/js-bun-db/js/pg-leftover.mdc +27 -0
  101. package/rules/js-bun-db/js/pg-listen-notify.mdc +51 -0
  102. package/rules/js-bun-db/js/query-safety.mdc +117 -0
  103. package/rules/js-bun-db/js/sql-array.mdc +88 -0
  104. package/rules/js-bun-db/js/unsafe.mdc +65 -0
  105. package/rules/js-bun-db/main.mdc +12 -607
  106. package/rules/js-bun-db/policy/package_json/package_json.mdc +17 -0
  107. package/rules/js-bun-redis/js/imports.mdc +47 -0
  108. package/rules/js-bun-redis/js/package_json.mdc +44 -0
  109. package/rules/js-bun-redis/main.mdc +4 -10
  110. package/rules/js-bun-redis/policy/package_json/package_json.mdc +11 -0
  111. package/rules/js-mssql/js/mssql-in-list.mdc +38 -0
  112. package/rules/js-mssql/js/mssql-pool.mdc +56 -0
  113. package/rules/js-mssql/js/mssql-query-template.mdc +33 -0
  114. package/rules/js-mssql/js/mssql-tvp.mdc +75 -0
  115. package/rules/js-mssql/js/mssql-version.mdc +7 -0
  116. package/rules/js-mssql/main.mdc +10 -198
  117. package/rules/js-mssql/policy/package_json/package_json.mdc +9 -0
  118. package/rules/js-run/js/check-env.mdc +35 -0
  119. package/rules/js-run/js/conn-aliases.mdc +109 -0
  120. package/rules/js-run/js/jsconfig.mdc +20 -0
  121. package/rules/js-run/js/otel-configmap.mdc +6 -0
  122. package/rules/js-run/js/pino.mdc +6 -0
  123. package/rules/js-run/js/project-structure.mdc +11 -0
  124. package/rules/js-run/js/runtime.mdc +14 -0
  125. package/rules/js-run/js/scope.mdc +11 -0
  126. package/rules/js-run/js/settimeout.mdc +11 -0
  127. package/rules/js-run/js/temporal.mdc +5 -0
  128. package/rules/js-run/main.mdc +16 -216
  129. package/rules/js-run/policy/configmap/configmap.mdc +31 -0
  130. package/rules/js-run/policy/jsconfig/jsconfig.mdc +25 -0
  131. package/rules/js-run/policy/package_json/package_json.mdc +38 -0
  132. package/rules/k8s/js/configmap.mdc +41 -0
  133. package/rules/k8s/js/deployment_resources.mdc +49 -0
  134. package/rules/k8s/js/hasura_httproute.mdc +91 -0
  135. package/rules/k8s/js/hpa_apiversion.mdc +27 -0
  136. package/rules/k8s/js/ingress_gateway.mdc +16 -0
  137. package/rules/k8s/js/kustomize_structure.mdc +144 -0
  138. package/rules/k8s/js/lint_k8s.mdc +72 -0
  139. package/rules/k8s/js/multidoc_yaml.mdc +5 -0
  140. package/rules/k8s/js/network_policy.mdc +136 -0
  141. package/rules/k8s/js/schema_modeline.mdc +57 -0
  142. package/rules/k8s/js/service.mdc +44 -0
  143. package/rules/k8s/js/topology_hpa_pdb.mdc +181 -0
  144. package/rules/k8s/main.mdc +29 -834
  145. package/rules/k8s/policy/base_kustomization/base_kustomization.mdc +12 -0
  146. package/rules/k8s/policy/base_manifest/base_manifest.mdc +14 -0
  147. package/rules/k8s/policy/gateway/gateway.mdc +17 -0
  148. package/rules/k8s/policy/hasura_configmap/hasura_configmap.mdc +20 -0
  149. package/rules/k8s/policy/hasura_httproute/hasura_httproute.mdc +16 -0
  150. package/rules/k8s/policy/hpa_pdb/hpa_pdb.mdc +23 -0
  151. package/rules/k8s/policy/kustomization/kustomization.mdc +20 -0
  152. package/rules/k8s/policy/manifest/manifest.mdc +17 -0
  153. package/rules/k8s/policy/network_policy/network_policy.mdc +22 -0
  154. package/rules/k8s/policy/svc_hl_yaml/svc_hl_yaml.mdc +13 -0
  155. package/rules/k8s/policy/svc_yaml/svc_yaml.mdc +12 -0
  156. package/rules/nginx-default-tpl/js/dockerfile.mdc +36 -0
  157. package/rules/nginx-default-tpl/js/http-route.mdc +41 -0
  158. package/rules/nginx-default-tpl/js/ini-keys.mdc +21 -0
  159. package/rules/nginx-default-tpl/js/template-structure.mdc +86 -0
  160. package/rules/nginx-default-tpl/js/vscode.mdc +37 -0
  161. package/rules/nginx-default-tpl/main.mdc +8 -110
  162. package/rules/nginx-default-tpl/policy/vscode_extensions/vscode_extensions.mdc +11 -0
  163. package/rules/nginx-default-tpl/policy/vscode_settings/vscode_settings.mdc +15 -0
  164. package/rules/npm-module/js/docs/index.md +5 -5
  165. package/rules/npm-module/js/docs/rule_meta.md +6 -6
  166. package/rules/npm-module/js/docs/skill_meta.md +8 -8
  167. package/rules/npm-module/js/header_doc_pointer.mdc +18 -0
  168. package/rules/npm-module/js/package_structure.mdc +62 -0
  169. package/rules/npm-module/js/rule_meta.mdc +11 -0
  170. package/rules/npm-module/js/skill_meta.mdc +11 -0
  171. package/rules/npm-module/main.mdc +10 -52
  172. package/rules/npm-module/policy/emit_types_config/emit_types_config.mdc +40 -0
  173. package/rules/npm-module/policy/npm_package_json/npm_package_json.mdc +50 -0
  174. package/rules/npm-module/policy/root_package_json/root_package_json.mdc +37 -0
  175. package/rules/php/js/lint_php_yml.mdc +12 -0
  176. package/rules/php/js/tooling.mdc +66 -0
  177. package/rules/php/main.mdc +5 -66
  178. package/rules/php/policy/lint_php_yml/lint_php_yml.mdc +21 -0
  179. package/rules/python/js/lint_python_yml.mdc +23 -0
  180. package/rules/python/js/pyproject_toml.mdc +32 -0
  181. package/rules/python/js/tooling.mdc +23 -0
  182. package/rules/python/main.mdc +7 -32
  183. package/rules/python/policy/lint_python_yml/lint_python_yml.mdc +12 -0
  184. package/rules/python/policy/pyproject_toml/pyproject_toml.mdc +13 -0
  185. package/rules/rego/js/rego-lint.mdc +31 -0
  186. package/rules/rego/js/vscode_extensions.mdc +11 -0
  187. package/rules/rego/js/vscode_settings.mdc +13 -0
  188. package/rules/rego/main.mdc +10 -22
  189. package/rules/rego/policy/vscode_extensions/vscode_extensions.mdc +11 -0
  190. package/rules/rego/policy/vscode_settings/vscode_settings.mdc +19 -0
  191. package/rules/rust/js/coverage.mdc +28 -0
  192. package/rules/rust/js/lint.mdc +22 -0
  193. package/rules/rust/js/tauri_composition.mdc +8 -0
  194. package/rules/rust/js/vscode_extensions.mdc +12 -0
  195. package/rules/rust/main.mdc +8 -38
  196. package/rules/rust/policy/lint_rust_yml/lint_rust_yml.mdc +12 -0
  197. package/rules/rust/policy/vscode_extensions/vscode_extensions.mdc +9 -0
  198. package/rules/security/js/rego_policies.mdc +15 -0
  199. package/rules/security/js/sample_secret.mdc +19 -0
  200. package/rules/security/js/trufflehog.mdc +21 -0
  201. package/rules/security/main.mdc +7 -34
  202. package/rules/security/policy/lint_security_yml/lint_security_yml.mdc +7 -0
  203. package/rules/security/policy/package_json/package_json.mdc +7 -0
  204. package/rules/style/js/admin-table.mdc +88 -0
  205. package/rules/style/js/colors.mdc +21 -0
  206. package/rules/style/js/gap.mdc +22 -0
  207. package/rules/style/js/quasar-fixes.mdc +32 -0
  208. package/rules/style/js/quasar.mdc +7 -0
  209. package/rules/style/js/tooling.mdc +85 -0
  210. package/rules/style/main.mdc +12 -251
  211. package/rules/style/policy/lint_style_yml/lint_style_yml.mdc +13 -0
  212. package/rules/style/policy/package_json/package_json.mdc +18 -0
  213. package/rules/style/policy/vscode_extensions/vscode_extensions.mdc +13 -0
  214. package/rules/style/policy/vscode_settings/vscode_settings.mdc +19 -0
  215. package/rules/tauri/js/cargo_mutants_config.mdc +39 -0
  216. package/rules/tauri/js/tool_surface.mdc +21 -0
  217. package/rules/tauri/js/tooling.mdc +25 -0
  218. package/rules/tauri/main.mdc +6 -78
  219. package/rules/tauri/policy/vscode_extensions/vscode_extensions.mdc +21 -0
  220. package/rules/test/js/cargo_mutants_config.mdc +18 -0
  221. package/rules/test/js/docs/index.md +7 -7
  222. package/rules/test/js/location.mdc +52 -0
  223. package/rules/test/js/no-console-store-restore.mdc +11 -0
  224. package/rules/test/js/no-process-chdir.mdc +15 -0
  225. package/rules/test/js/no-relative-fs-path.mdc +22 -0
  226. package/rules/test/js/sandbox-aware-test.mdc +28 -0
  227. package/rules/test/js/stryker_config.mdc +26 -0
  228. package/rules/test/js/vitest-config-pool-forks.mdc +33 -0
  229. package/rules/test/main.mdc +16 -184
  230. package/rules/test/policy/package_json/package_json.mdc +16 -0
  231. package/rules/text/js/ci-lint-text.mdc +15 -0
  232. package/rules/text/js/cspell.mdc +81 -0
  233. package/rules/text/js/dotenv-linter.mdc +16 -0
  234. package/rules/text/js/forbidden-prettier.mdc +13 -0
  235. package/rules/text/js/markdownlint.mdc +25 -0
  236. package/rules/text/js/oxfmt.mdc +35 -0
  237. package/rules/text/js/package-json.mdc +26 -0
  238. package/rules/text/js/shellcheck.mdc +18 -0
  239. package/rules/text/js/v8r.mdc +23 -0
  240. package/rules/text/js/vscode.mdc +86 -0
  241. package/rules/text/main.mdc +20 -231
  242. package/rules/text/policy/cspell/cspell.mdc +34 -0
  243. package/rules/text/policy/lint_text/lint_text.mdc +19 -0
  244. package/rules/text/policy/markdownlint/markdownlint.mdc +38 -0
  245. package/rules/text/policy/oxfmtrc/oxfmtrc.mdc +11 -0
  246. package/rules/text/policy/package_json/package_json.mdc +33 -0
  247. package/rules/text/policy/vscode_extensions/vscode_extensions.mdc +13 -0
  248. package/rules/text/policy/vscode_settings/vscode_settings.mdc +13 -0
  249. package/rules/vue/js/composition-api.mdc +82 -0
  250. package/rules/vue/js/nheader-layout.mdc +171 -0
  251. package/rules/vue/js/node-imports.mdc +25 -0
  252. package/rules/vue/js/quasar-ui.mdc +32 -0
  253. package/rules/vue/js/structure.mdc +101 -0
  254. package/rules/vue/js/testing.mdc +32 -0
  255. package/rules/vue/js/tfm-translations.mdc +26 -0
  256. package/rules/vue/js/vite-config.mdc +126 -0
  257. package/rules/vue/js/vite-env.mdc +55 -0
  258. package/rules/vue/js/vue-imports.mdc +25 -0
  259. package/rules/vue/main.mdc +15 -641
  260. package/rules/vue/policy/package_json/package_json.mdc +30 -0
  261. package/scripts/docs/index.md +16 -16
  262. package/scripts/lib/docs/index.md +36 -36
  263. package/scripts/utils/docs/index.md +14 -14
@@ -0,0 +1,109 @@
1
+ ## Внутрішні аліаси для підключень до БД і GraphQL
2
+
3
+ Якщо в проекті є підключення до баз даних, зовнішніх graphql на кшталт:
4
+
5
+ ```js
6
+ import { SQL } from 'bun'
7
+
8
+ // або
9
+
10
+ import sql from 'mssql'
11
+
12
+ // або
13
+
14
+ import { GraphQLClient } from '@nitra/graphql-request'
15
+ ```
16
+
17
+ то ці підключення повинні бути винесені в окремий файл, наприклад `/src/conn/pg.mjs`, в package.json повинні бути додано аліас:
18
+
19
+ ```json
20
+ {
21
+ "imports": {
22
+ "#conn/*": "./src/conn/*"
23
+ },
24
+ }
25
+
26
+ ```
27
+
28
+ так виглядатиме підключення до PostgreSQL в коді:
29
+
30
+ ```javascript title="Приклад підключення до PostgreSQL в /src/conn/pg.mjs"
31
+ import { checkEnv, env } from '@nitra/check-env'
32
+ import { SQL } from 'bun'
33
+
34
+ checkEnv(['PG_CONN'])
35
+
36
+ export const db = new SQL({ url: env.PG_CONN })
37
+
38
+ ```
39
+
40
+ а так до GraphQL:
41
+
42
+ ```js
43
+ import { checkEnv, env } from '@nitra/check-env'
44
+ import { GraphQLClient } from '@nitra/graphql-request'
45
+
46
+ checkEnv(['QL', 'X_HASURA_ADMIN_SECRET'])
47
+
48
+ export { gql } from '@nitra/graphql-request'
49
+
50
+ export const graphQLClientSmart = new GraphQLClient(env.QL, {
51
+ headers: {
52
+ 'X-Hasura-Admin-Secret': env.X_HASURA_ADMIN_SECRET
53
+ }
54
+ })
55
+ ```
56
+
57
+ а в коді повинно бути використано:
58
+
59
+ ```js
60
+ import { pool } from '#conn/pg.mjs'
61
+
62
+ // або
63
+
64
+ import { gql, graphQLClient } from '@nitra/graphql-request'
65
+ ```
66
+
67
+ ### Нейминг файлів у `src/conn/`
68
+
69
+ Назва файла в `src/conn/` має одразу повідомляти, **до чого** підключаємось і **в якому режимі**:
70
+
71
+ - **GraphQL** — префікс `ql-`, далі ідентифікатор endpoint:
72
+ - `src/conn/ql-contract.mjs`
73
+ - `src/conn/ql-smart.mjs`
74
+ - **PostgreSQL** — префікс `pg-`, далі тип підключення (репліка vs мастер): `read` або `write`:
75
+ - `src/conn/pg-read.mjs`
76
+ - `src/conn/pg-write.mjs`
77
+ - **PostgreSQL до кількох БД** — додатково ідентифікатор підключення після типу:
78
+ - `src/conn/pg-read-smart.mjs`
79
+ - `src/conn/pg-write-contract.mjs`
80
+ - **MySQL** — префікс `mysql-` за тією ж схемою (`mysql-read.mjs`, `mysql-write-<id>.mjs` тощо).
81
+ - **MSSQL** — префікс `mssql-` за тією ж схемою (`mssql-read.mjs`, `mssql-write-<id>.mjs` тощо). Хоча npm-пакет один (`mssql`), а драйвер MS SQL Server під капотом T-SQL — у файловій назві відрізняємо MS SQL Server від MySQL, бо це різні СУБД, різні діалекти, різні рантаймні залежності. Якщо проєкт історично використовує `mysql-…` для MSSQL-підключень — він валідний і далі (для backward-compat), але новий код пишемо з префіксом `mssql-`.
82
+
83
+ Підключення до БД **обов'язково** має бути ідентифіковано як `read` (репліка) або `write` (мастер). Якщо з імені змінної оточення (наприклад, `env.PG_CONN`) це не очевидно — визнач режим за операціями в коді: якщо немає операцій зміни даних (`INSERT`/`UPDATE`/`DELETE`/DDL) — це `pg-read.mjs`, інакше `pg-write.mjs`.
84
+
85
+ ### Експорти у файлах `src/conn/`
86
+
87
+ У файлах підключень **заборонений** `export default`. Експорт має бути **іменований** і збігатися з назвою файла в camelCase.
88
+
89
+ Приклад — `src/conn/ql-smart.mjs`:
90
+
91
+ ```javascript title="❌ Так не можна"
92
+ export default new GraphQLClient(env.SMART_QL, {
93
+ headers: {
94
+ 'X-Hasura-Admin-Secret': env.SMART_X_HASURA_ADMIN_SECRET
95
+ }
96
+ })
97
+ ```
98
+
99
+ ```javascript title="✅ Канон: іменований експорт за іменем файла"
100
+ export const qlSmart = new GraphQLClient(env.SMART_QL, {
101
+ headers: {
102
+ 'X-Hasura-Admin-Secret': env.SMART_X_HASURA_ADMIN_SECRET
103
+ }
104
+ })
105
+ ```
106
+
107
+ Відповідно: `pg-read.mjs` → `export const pgRead = …`, `pg-write-contract.mjs` → `export const pgWriteContract = …`, `ql-contract.mjs` → `export const qlContract = …`.
108
+
109
+ Файли `index.*` у conn-каталозі пропускаються як можливий reexport-барель.
@@ -0,0 +1,20 @@
1
+ ## `jsconfig.json` (редактор / перевірка типів)
2
+
3
+ Якщо в **backend** workspace-пакеті (без `vite` у `devDependencies`) є каталог **`src/`**, у **корені цього пакета** має бути **`jsconfig.json`**. Якщо файлу ще немає — створи його з таким вмістом (канон js-run):
4
+
5
+ ```json title="jsconfig.json"
6
+ {
7
+ "compilerOptions": {
8
+ "lib": ["esnext"],
9
+ "module": "NodeNext",
10
+ "moduleResolution": "NodeNext",
11
+ "target": "esnext",
12
+ "checkJs": false
13
+ },
14
+ "include": ["src/**/*"]
15
+ }
16
+ ```
17
+
18
+ Канон: [jsconfig.json.snippet.json](./policy/jsconfig/template/jsconfig.json.snippet.json)
19
+
20
+ Якщо пакет не слідує структурі з `src/` (наприклад, лише `scripts/` у корені) — ця вимога не застосовується; для типових сервісів із `src/` файл обов'язковий і має збігатися з каноном.
@@ -0,0 +1,6 @@
1
+ ## OTEL ConfigMap (k8s)
2
+
3
+ В **/k8s/base/configmap.yaml** повинен бути заданий `OTEL_RESOURCE_ATTRIBUTES: 'service.name=<project_name>,service.namespace=<project_namespace>'`
4
+ а в директоріях з kustomize повинні бути перевизначені значення `OTEL_RESOURCE_ATTRIBUTES` і в них `service.namespace` повинен відповідати namespace, в якому знаходиться дана директорія.
5
+
6
+ Канон обовʼязкових substring у `data.OTEL_RESOURCE_ATTRIBUTES` (`service.name=`, `service.namespace=`): [configmap.yaml.contains.yml](./policy/configmap/template/configmap.yaml.contains.yml)
@@ -0,0 +1,6 @@
1
+ ## Використання @nitra/pino для логування
2
+
3
+ Проект використовує @nitra/pino для логування.
4
+ Якщо в проекті присутній @nitra/bunyan, то він повинен бути замінений на @nitra/pino — як у `package.json`, так і в коді: усі `import` / `require` / динамічні `import()` з `@nitra/bunyan` (і застарілого `bunyan`) треба замінити на `@nitra/pino` і за потреби адаптувати виклики під його API.
5
+
6
+ Канон заборонених `dependencies` / `devDependencies` (`bunyan`, `@nitra/bunyan`): [package.json.deny.json](./policy/package_json/template/package.json.deny.json)
@@ -0,0 +1,11 @@
1
+ ## Структура проекту
2
+
3
+ Рекомендується використовувати таку структуру проекту:
4
+
5
+ ```
6
+ k8s/ # тут всі файли для деплойменту в Kubernetes, включаючи kustomize
7
+ src/ # тут всі файли необхідні для роботи проекту
8
+ Dockerfile
9
+ package.json
10
+ readme.md
11
+ ```
@@ -0,0 +1,14 @@
1
+ ## Runtime у `package.json#scripts`
2
+
3
+ У **backend**-пакетах (без `vite` у `devDependencies`) код запускають через **Bun**, не через бінарник **`node`** у значеннях `scripts`:
4
+
5
+ - `"start": "node src/index.js"` → `"start": "bun src/index.js"` (або `bun run …`, якщо так прийнято в репо);
6
+ - `node --watch app.js` → `bun --watch app.js`;
7
+ - `NODE_OPTIONS=… node app.js` → `NODE_OPTIONS=… bun app.js`.
8
+ - `env $(cat .env .env.local) bun src/index.js` → `bun --env-file=.env --env-file=.env.local src/index.js` (нативне завантаження env у Bun, без `env`/`cat`).
9
+
10
+ Заборонено викликати **`node`** у ланцюжках (`&&`, `;`, `|`). Заборонено обгортку **`env $(cat …) bun`** — файли з `cat` перелічуй у **`--env-file=`** (по одному прапорцю на файл, порядок як у `cat`). Допустимо: `bun`, `bunx`, `npx` (див. **bun.mdc**), інші CLI, якщо вони не підміняють рантайм на `node`.
11
+
12
+ Це **не** стосується поля `engines.node` (мінімальна версія Node для сумісності інструментів) і **не** стосується frontend-пакетів з `vite` у `devDependencies`.
13
+
14
+ Канон заборонених патернів у `scripts`: [package.json.deny.json](./policy/package_json/template/package.json.deny.json) (`scriptsForbidden`).
@@ -0,0 +1,11 @@
1
+ ## Область застосування
2
+
3
+ Правило стосується **виключно backend Node.js workspace-пакетів** (jobs, GraphQL/HTTP-сервери, CLI). **Не застосовується** до frontend-пакетів, які бандляться в браузер: маркер — наявність `vite` у `devDependencies` пакета (`site/`, мобільні Capacitor-пакети, будь-яка Vue/Quasar SPA).
4
+
5
+ У браузерному середовищі:
6
+
7
+ - немає `node:process` — імпорт `import { env } from 'node:process'` resolve'иться у `undefined`, і `env.X` падає з `TypeError: Cannot read properties of undefined`;
8
+ - `process.env.X` у джерелах пакета відсутнє в рантаймі — Vite або взагалі не підставляє його, або підставляє лише `process.env.NODE_ENV`;
9
+ - усі змінні оточення для frontend задаються через `VITE_*` і доступні як `import.meta.env.VITE_X` (типобезпечно через `vite-check-env`); режим — `import.meta.env.MODE` / `import.meta.env.PROD`.
10
+
11
+ Тому **у frontend-пакетах не торкайся `process.env.*`** і **не додавай** `import { env } from 'node:process'`. Якщо натрапив на `process.env.NODE_ENV` у frontend-коді — заміна, якщо взагалі потрібна, лише на `import.meta.env.MODE`.
@@ -0,0 +1,11 @@
1
+ ## Паузи через setTimeout
2
+
3
+ Заборонено робити паузи через `await new Promise(resolve => setTimeout(resolve, ms))` — таку обгортку треба замінити на promise-варіант `setTimeout` з `node:timers/promises`:
4
+
5
+ ```javascript title="Замість new Promise + setTimeout"
6
+ import { setTimeout } from 'node:timers/promises'
7
+
8
+ await setTimeout(500)
9
+ ```
10
+
11
+ Імпорт `setTimeout` з `node:timers/promises` затіняє глобальний таймер у файлі — якщо в тому ж файлі потрібен callback-варіант, імпортуй його під іншим іменем (наприклад, `import { setTimeout as setTimeoutCb } from 'node:timers'`).
@@ -0,0 +1,5 @@
1
+ ## Temporal API (заборона у Bun runtime)
2
+
3
+ У backend/Bun runtime-коді **не використовуй `Temporal`** (`Temporal.Now`, `Temporal.Instant`, імпорти з polyfill тощо). Поточний Bun runtime ще не має глобального `Temporal` (`typeof Temporal === "undefined"`), тому агентам треба лишатися на сумісному `Date` API або передавати timestamp у чисті функції через параметр.
4
+
5
+ Перевірка `npx @nitra/cursor fix js-run` сканує JS/TS AST і падає на identifier `Temporal` у backend workspace-коді.
@@ -5,234 +5,34 @@ alwaysApply: false
5
5
  version: '1.12'
6
6
  ---
7
7
 
8
- ## Область застосування
8
+ Правило охоплює backend Node.js workspace-пакети (jobs, GraphQL/HTTP-сервери, CLI) — визначення меж застосування, вимоги до runtime, структуру проекту, конфігурацію, логування, підключення до БД/GraphQL і безпечне використання env-змінних.
9
9
 
10
- Правило стосується **виключно backend Node.js workspace-пакетів** (jobs, GraphQL/HTTP-сервери, CLI). **Не застосовується** до frontend-пакетів, які бандляться в браузер: маркер — наявність `vite` у `devDependencies` пакета (`site/`, мобільні Capacitor-пакети, будь-яка Vue/Quasar SPA).
10
+ [js-run-scope](./js/scope.mdc)
11
11
 
12
- У браузерному середовищі:
12
+ [js-run-runtime](./js/runtime.mdc)
13
13
 
14
- - немає `node:process` — імпорт `import { env } from 'node:process'` resolve'иться у `undefined`, і `env.X` падає з `TypeError: Cannot read properties of undefined`;
15
- - `process.env.X` у джерелах пакета відсутнє в рантаймі — Vite або взагалі не підставляє його, або підставляє лише `process.env.NODE_ENV`;
16
- - усі змінні оточення для frontend задаються через `VITE_*` і доступні як `import.meta.env.VITE_X` (типобезпечно через `vite-check-env`); режим — `import.meta.env.MODE` / `import.meta.env.PROD`.
14
+ [js-run-temporal](./js/temporal.mdc)
17
15
 
18
- Тому **у frontend-пакетах не торкайся `process.env.*`** і **не додавай** `import { env } from 'node:process'`. Якщо натрапив на `process.env.NODE_ENV` у frontend-коді — заміна, якщо взагалі потрібна, лише на `import.meta.env.MODE`.
16
+ [js-run-project-structure](./js/project-structure.mdc)
19
17
 
20
- ## Runtime у `package.json#scripts`
18
+ [js-run-jsconfig](./js/jsconfig.mdc)
21
19
 
22
- У **backend**-пакетах (без `vite` у `devDependencies`) код запускають через **Bun**, не через бінарник **`node`** у значеннях `scripts`:
20
+ [js-run-pino](./js/pino.mdc)
23
21
 
24
- - `"start": "node src/index.js"` → `"start": "bun src/index.js"` (або `bun run …`, якщо так прийнято в репо);
25
- - `node --watch app.js` → `bun --watch app.js`;
26
- - `NODE_OPTIONS=… node app.js` → `NODE_OPTIONS=… bun app.js`.
27
- - `env $(cat .env .env.local) bun src/index.js` → `bun --env-file=.env --env-file=.env.local src/index.js` (нативне завантаження env у Bun, без `env`/`cat`).
22
+ [js-run-otel-configmap](./js/otel-configmap.mdc)
28
23
 
29
- Заборонено викликати **`node`** у ланцюжках (`&&`, `;`, `|`). Заборонено обгортку **`env $(cat …) bun`** — файли з `cat` перелічуй у **`--env-file=`** (по одному прапорцю на файл, порядок як у `cat`). Допустимо: `bun`, `bunx`, `npx` (див. **bun.mdc**), інші CLI, якщо вони не підміняють рантайм на `node`.
24
+ [js-run-conn-aliases](./js/conn-aliases.mdc)
30
25
 
31
- Це **не** стосується поля `engines.node` (мінімальна версія Node для сумісності інструментів) і **не** стосується frontend-пакетів з `vite` у `devDependencies`.
26
+ [js-run-check-env](./js/check-env.mdc)
32
27
 
33
- ## Temporal API
28
+ [js-run-settimeout](./js/settimeout.mdc)
34
29
 
35
- У backend/Bun runtime-коді **не використовуй `Temporal`** (`Temporal.Now`, `Temporal.Instant`, імпорти з polyfill тощо). Поточний Bun runtime ще не має глобального `Temporal` (`typeof Temporal === "undefined"`), тому агентам треба лишатися на сумісному `Date` API або передавати timestamp у чисті функції через параметр.
30
+ ## Швидкий gate через conftest
36
31
 
37
- Перевірка `npx @nitra/cursor fix js-run` сканує JS/TS AST і падає на identifier `Temporal` у backend workspace-коді.
32
+ Rego-пакети, які запускає `npx @nitra/cursor fix js-run` / `npx @nitra/cursor check`:
38
33
 
39
- Канон заборонених патернів у `scripts`: [package.json.deny.json](./policy/package_json/template/package.json.deny.json) (`scriptsForbidden`).
34
+ [js-run-package_json](./policy/package_json/package_json.mdc)
40
35
 
41
- ## Структура проекту
36
+ [js-run-jsconfig](./policy/jsconfig/jsconfig.mdc)
42
37
 
43
- Рекомендується використовувати таку структуру проекту:
44
-
45
- ```
46
- k8s/ # тут всі файли для деплойменту в Kubernetes, включаючи kustomize
47
- src/ # тут всі файли необхідні для роботи проекту
48
- Dockerfile
49
- package.json
50
- readme.md
51
- ```
52
-
53
- ## `jsconfig.json` (редактор / перевірка типів)
54
-
55
- Якщо в **backend** workspace-пакеті (без `vite` у `devDependencies`) є каталог **`src/`**, у **корені цього пакета** має бути **`jsconfig.json`**. Якщо файлу ще немає — створи його з таким вмістом (канон js-run):
56
-
57
- ```json title="jsconfig.json"
58
- {
59
- "compilerOptions": {
60
- "lib": ["esnext"],
61
- "module": "NodeNext",
62
- "moduleResolution": "NodeNext",
63
- "target": "esnext",
64
- "checkJs": false
65
- },
66
- "include": ["src/**/*"]
67
- }
68
- ```
69
-
70
- Канон: [jsconfig.json.snippet.json](./policy/jsconfig/template/jsconfig.json.snippet.json)
71
-
72
- Якщо пакет не слідує структурі з `src/` (наприклад, лише `scripts/` у корені) — ця вимога не застосовується; для типових сервісів із `src/` файл обов’язковий і має збігатися з каноном.
73
-
74
- ## Використання @nitra/pino
75
-
76
- Проект використовує @nitra/pino для логування.
77
- Якщо в проекті присутній @nitra/bunyan, то він повинен бути замінений на @nitra/pino — як у `package.json`, так і в коді: усі `import` / `require` / динамічні `import()` з `@nitra/bunyan` (і застарілого `bunyan`) треба замінити на `@nitra/pino` і за потреби адаптувати виклики під його API. Канон заборонених `dependencies` / `devDependencies` (`bunyan`, `@nitra/bunyan`): [package.json.deny.json](./policy/package_json/template/package.json.deny.json)
78
-
79
- В **/k8s/base/configmap.yaml повинен бути заданий OTEL_RESOURCE_ATTRIBUTES: 'service.name=<project_name>,service.namespace=<project_namespace>'
80
- а в директоріях з kustomize повинні бути перевизначені значення OTEL_RESOURCE_ATTRIBUTES і в них service.namespace повинен відповідати namespace, в якому знаходиться дана директорія.
81
-
82
- Канон обовʼязкових substring у `data.OTEL_RESOURCE_ATTRIBUTES` (`service.name=`, `service.namespace=`): [configmap.yaml.contains.yml](./policy/configmap/template/configmap.yaml.contains.yml)
83
-
84
- ## Внутрішні аліаси
85
-
86
- Якщо в проекті є підключення до баз даних, зовнішніх graphql на кшталт:
87
-
88
- ```js
89
- import { SQL } from 'bun'
90
-
91
- // або
92
-
93
- import sql from 'mssql'
94
-
95
- // або
96
-
97
- import { GraphQLClient } from '@nitra/graphql-request'
98
- ```
99
-
100
- то ці підключення повинні бути винесені в окремий файл, наприклад `/src/conn/pg.mjs`, в package.json повинні бути додано аліас:
101
-
102
- ```json
103
- {
104
- "imports": {
105
- "#conn/*": "./src/conn/*"
106
- },
107
- }
108
-
109
- ```
110
-
111
- так виглядатиме підключення до PostgreSQL в коді:
112
-
113
- ```javascript title="Приклад підключення до PostgreSQL в /src/conn/pg.mjs"
114
- import { checkEnv, env } from '@nitra/check-env'
115
- import { SQL } from 'bun'
116
-
117
- checkEnv(['PG_CONN'])
118
-
119
- export const db = new SQL({ url: env.PG_CONN })
120
-
121
- ```
122
-
123
- а так до GraphQL:
124
-
125
- ```js
126
- import { checkEnv, env } from '@nitra/check-env'
127
- import { GraphQLClient } from '@nitra/graphql-request'
128
-
129
- checkEnv(['QL', 'X_HASURA_ADMIN_SECRET'])
130
-
131
- export { gql } from '@nitra/graphql-request'
132
-
133
- export const graphQLClientSmart = new GraphQLClient(env.QL, {
134
- headers: {
135
- 'X-Hasura-Admin-Secret': env.X_HASURA_ADMIN_SECRET
136
- }
137
- })
138
- ```
139
-
140
- а в коді повинно бути використано:
141
-
142
- ```js
143
- import { pool } from '#conn/pg.mjs'
144
-
145
- // або
146
-
147
- import { gql, graphQLClient } from '@nitra/graphql-request'
148
- ```
149
-
150
- ### Нейминг файлів у `src/conn/`
151
-
152
- Назва файла в `src/conn/` має одразу повідомляти, **до чого** підключаємось і **в якому режимі**:
153
-
154
- - **GraphQL** — префікс `ql-`, далі ідентифікатор endpoint:
155
- - `src/conn/ql-contract.mjs`
156
- - `src/conn/ql-smart.mjs`
157
- - **PostgreSQL** — префікс `pg-`, далі тип підключення (репліка vs мастер): `read` або `write`:
158
- - `src/conn/pg-read.mjs`
159
- - `src/conn/pg-write.mjs`
160
- - **PostgreSQL до кількох БД** — додатково ідентифікатор підключення після типу:
161
- - `src/conn/pg-read-smart.mjs`
162
- - `src/conn/pg-write-contract.mjs`
163
- - **MySQL** — префікс `mysql-` за тією ж схемою (`mysql-read.mjs`, `mysql-write-<id>.mjs` тощо).
164
- - **MSSQL** — префікс `mssql-` за тією ж схемою (`mssql-read.mjs`, `mssql-write-<id>.mjs` тощо). Хоча npm-пакет один (`mssql`), а драйвер MS SQL Server під капотом T-SQL — у файловій назві відрізняємо MS SQL Server від MySQL, бо це різні СУБД, різні діалекти, різні рантаймні залежності. Якщо проєкт історично використовує `mysql-…` для MSSQL-підключень — він валідний і далі (для backward-compat), але новий код пишемо з префіксом `mssql-`.
165
-
166
- Підключення до БД **обов'язково** має бути ідентифіковано як `read` (репліка) або `write` (мастер). Якщо з імені змінної оточення (наприклад, `env.PG_CONN`) це не очевидно — визнач режим за операціями в коді: якщо немає операцій зміни даних (`INSERT`/`UPDATE`/`DELETE`/DDL) — це `pg-read.mjs`, інакше `pg-write.mjs`.
167
-
168
- ### Експорти у файлах `src/conn/`
169
-
170
- У файлах підключень **заборонений** `export default`. Експорт має бути **іменований** і збігатися з назвою файла в camelCase.
171
-
172
- Приклад — `src/conn/ql-smart.mjs`:
173
-
174
- ```javascript title="❌ Так не можна"
175
- export default new GraphQLClient(env.SMART_QL, {
176
- headers: {
177
- 'X-Hasura-Admin-Secret': env.SMART_X_HASURA_ADMIN_SECRET
178
- }
179
- })
180
- ```
181
-
182
- ```javascript title="✅ Канон: іменований експорт за іменем файла"
183
- export const qlSmart = new GraphQLClient(env.SMART_QL, {
184
- headers: {
185
- 'X-Hasura-Admin-Secret': env.SMART_X_HASURA_ADMIN_SECRET
186
- }
187
- })
188
- ```
189
-
190
- Відповідно: `pg-read.mjs` → `export const pgRead = …`, `pg-write-contract.mjs` → `export const pgWriteContract = …`, `ql-contract.mjs` → `export const qlContract = …`.
191
-
192
- ## CheckEnv
193
-
194
- Усі змінні оточення, які використовуються в коді, повинні бути перевірені за допомогою `checkEnv` з пакету `@nitra/check-env`. Це гарантує, що всі необхідні змінні оточення встановлені перед запуском програми.
195
-
196
- ```javascript title="Приклад підключення до PostgreSQL в /src/conn/pg.mjs"
197
- import { checkEnv, env } from '@nitra/check-env'
198
- import { SQL } from 'bun'
199
-
200
- checkEnv(['PG_CONN'])
201
-
202
- export const db = new SQL({ url: env.PG_CONN })
203
-
204
- ```
205
-
206
- ## process.env
207
-
208
- Прямий доступ до `process.env.X` у коді заборонений — його треба замінити на `env`:
209
-
210
- > Стосується лише backend-пакетів (див. **Область застосування**). У frontend-пакетах (`vite` у `devDependencies`) — **не змінюй** `process.env.*` і **не додавай** імпорт `node:process`.
211
-
212
- - **обов'язкова змінна** — `import { checkEnv, env } from '@nitra/check-env'` плюс `checkEnv(['X'])`
213
- у тому ж файлі (приклад див. вище в розділі **CheckEnv**);
214
- - **опційна змінна** — `import { env } from 'node:process'`:
215
-
216
- ```javascript title="Опційна змінна — env з node:process"
217
- import { env } from 'node:process'
218
-
219
- console.log(env.OPTIONAL_ENV_VAR)
220
- ```
221
-
222
- Тимчасово приглушити перевірку для конкретного рядка можна коментарем
223
- `// @nitra/cursor ignore-next-line checkEnv` безпосередньо перед використанням
224
- (escape-hatch для legacy-коду, не для нових файлів).
225
-
226
- ## Паузи через setTimeout
227
-
228
- Заборонено робити паузи через `await new Promise(resolve => setTimeout(resolve, ms))` — таку обгортку треба замінити на promise-варіант `setTimeout` з `node:timers/promises`:
229
-
230
- ```javascript title="Замість new Promise + setTimeout"
231
- import { setTimeout } from 'node:timers/promises'
232
-
233
- await setTimeout(500)
234
- ```
235
-
236
- Імпорт `setTimeout` з `node:timers/promises` затіняє глобальний таймер у файлі — якщо в тому ж файлі потрібен callback-варіант, імпортуй його під іншим іменем (наприклад, `import { setTimeout as setTimeoutCb } from 'node:timers'`).
237
-
238
- Файли `index.*` у conn-каталозі пропускаються як можливий reexport-барель.
38
+ [js-run-configmap](./policy/configmap/configmap.mdc)
@@ -0,0 +1,31 @@
1
+ ## Rego-gate: OTEL ConfigMap (k8s)
2
+
3
+ Rego-пакет: `js-run.configmap`
4
+
5
+ **Цільові файли:** `k8s/base/configmap.yaml` (і будь-які ConfigMap у kustomize-оверлеях)
6
+
7
+ **Умова спрацювання:** `input.kind == "ConfigMap"`
8
+
9
+ Перевіряє, що поле `data.OTEL_RESOURCE_ATTRIBUTES` містить усі обовʼязкові substring-маркери, визначені у template:
10
+
11
+ - `service.name=`
12
+ - `service.namespace=`
13
+
14
+ Канон маркерів: [configmap.yaml.contains.yml](./template/configmap.yaml.contains.yml)
15
+
16
+ **✓ Правильно**
17
+
18
+ ```yaml
19
+ data:
20
+ OTEL_RESOURCE_ATTRIBUTES: 'service.name=my-svc,service.namespace=prod'
21
+ ```
22
+
23
+ **✗ Неправильно**
24
+
25
+ ```yaml
26
+ data:
27
+ OTEL_RESOURCE_ATTRIBUTES: 'service.name=my-svc'
28
+ # Відсутній service.namespace= → deny
29
+ ```
30
+
31
+ Ресурси типу `kind: Deployment` та інші non-ConfigMap — ігноруються.
@@ -0,0 +1,25 @@
1
+ ## Rego-gate: jsconfig.json
2
+
3
+ Rego-пакет: `js-run.jsconfig`
4
+
5
+ **Цільові файли:** `jsconfig.json` у корені backend workspace-пакету
6
+
7
+ Порівнює `jsconfig.json` з каноном через walker по всіх листах template:
8
+
9
+ - `compilerOptions.*` — значення мають збігатись точно
10
+ - `include` — масив порівнюється як множина (точний склад)
11
+
12
+ Канон: [jsconfig.json.snippet.json](./template/jsconfig.json.snippet.json)
13
+
14
+ Перевірені поля:
15
+
16
+ | Поле | Очікуване значення |
17
+ |------|--------------------|
18
+ | `compilerOptions.module` | `"NodeNext"` |
19
+ | `compilerOptions.moduleResolution` | `"NodeNext"` |
20
+ | `compilerOptions.target` | `"esnext"` |
21
+ | `compilerOptions.lib` | `["esnext"]` |
22
+ | `compilerOptions.checkJs` | `false` |
23
+ | `include` | `["src/**/*"]` |
24
+
25
+ Якщо розділ `compilerOptions` відсутній або не є обʼєктом — deny.
@@ -0,0 +1,38 @@
1
+ ## Rego-gate: package.json (залежності та scripts)
2
+
3
+ Rego-пакет: `js-run.package_json`
4
+
5
+ **Цільові файли:** `package.json` у backend workspace-пакетах (без `vite` у `devDependencies`)
6
+
7
+ Перевіряє три класи порушень за deny-списком із template:
8
+
9
+ Канон deny-списку: [package.json.deny.json](./template/package.json.deny.json)
10
+
11
+ **1. Заборонені залежності** (`dependencies` / `devDependencies`)
12
+
13
+ | Пакет | Причина |
14
+ |-------|---------|
15
+ | `bunyan` | використовуй стандартні логери |
16
+ | `@nitra/bunyan` | використовуй стандартні логери |
17
+
18
+ **2. Заборонений рантайм у `scripts`** (лише backend-пакети без `vite`)
19
+
20
+ - Патерн `\bnode(\s|$)` — заміни `node` на `bun`
21
+ - Патерн `\benv\s+\$\(cat\s+[^)]+\)\s+bun\b` — заміни `env $(cat A B) bun` на `bun --env-file=A --env-file=B`
22
+
23
+ **✓ Правильно**
24
+
25
+ ```json
26
+ { "scripts": { "start": "bun src/index.js" } }
27
+ { "scripts": { "start": "bun --env-file=.env src/index.js" } }
28
+ ```
29
+
30
+ **✗ Неправильно**
31
+
32
+ ```json
33
+ { "scripts": { "start": "node src/index.js" } }
34
+ { "scripts": { "start": "env $(cat .env .env.local) bun src/index.js" } }
35
+ { "dependencies": { "bunyan": "^1.0.0" } }
36
+ ```
37
+
38
+ Пакети з `vite` у `devDependencies` — frontend, поза областю js-run, перевірка scripts не застосовується.
@@ -0,0 +1,41 @@
1
+ ## ConfigMap: ім'я збігається з Deployment
2
+
3
+ Якщо в `k8s/base/` є **`configmap.yaml`** і **Deployment**, і цей Deployment посилається рівно на **один** ConfigMap — `metadata.name` ConfigMap має збігатися з `metadata.name` Deployment. Точні умови перевірки — **`rules/k8s/fix.mjs`**.
4
+
5
+ ## ConfigMap для Hasura-Deployment
6
+
7
+ Якщо в `k8s/base/` поруч із **`configmap.yaml`** є **Deployment** з образом **`hasura/graphql-engine`**, у `data` ConfigMap **обов'язково** мають бути env-ключі:
8
+
9
+ - **`HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS`** зі значенням **`"true"`**;
10
+ - **`HASURA_GRAPHQL_ENABLE_RELAY`** зі значенням **`"false"`**;
11
+ - **`HASURA_GRAPHQL_ENABLE_TELEMETRY`** зі значенням **`"false"`**;
12
+ - **`HASURA_GRAPHQL_ENABLED_LOG_TYPES`** зі значенням **`"startup,http-log"`** (точний рядок);
13
+ - **`HASURA_GRAPHQL_ENABLED_APIS`** зі значенням **`"metadata,graphql,pgdump"`** (точний рядок) — **значення для base/dev**;
14
+ - **`HASURA_GRAPHQL_DISABLE_EVENTING`** — ключ обов'язковий, значення довільне (за замовчуванням **`"true"`**).
15
+
16
+ Точні умови перевірки — rego-пакет **`k8s.hasura_configmap`** (cross-file прив'язка ConfigMap↔Deployment — у `rules/k8s/js/manifests.mjs`).
17
+
18
+ ```yaml
19
+ data:
20
+ HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS: 'true'
21
+ HASURA_GRAPHQL_ENABLE_RELAY: 'false'
22
+ HASURA_GRAPHQL_ENABLE_TELEMETRY: 'false'
23
+ HASURA_GRAPHQL_ENABLED_LOG_TYPES: 'startup,http-log'
24
+ HASURA_GRAPHQL_ENABLED_APIS: 'metadata,graphql,pgdump'
25
+ HASURA_GRAPHQL_DISABLE_EVENTING: 'true'
26
+ ```
27
+
28
+ ### `HASURA_GRAPHQL_ENABLED_APIS` поза base/dev
29
+
30
+ `pgdump` дозволено **лише** для **base**/**dev**. Кожен **не-base** overlay (`k8s/<env>/`, де `<env>` ≠ `base`/`dev`), що успадковує Hasura-base, **зобов'язаний** у своєму **`kustomization.yaml`** перевизначити `HASURA_GRAPHQL_ENABLED_APIS` до **`"metadata,graphql"`** (без `pgdump`) — патчем JSON6902 або Strategic Merge на ціль **ConfigMap**. Перевірка — cross-file у `rules/k8s/js/manifests.mjs` (`validateHasuraOverlayEnabledApisOverride`); `kind: Component` пропускається.
31
+
32
+ ```yaml title="k8s/prod/kustomization.yaml"
33
+ patches:
34
+ - target:
35
+ kind: ConfigMap
36
+ name: db-h
37
+ patch: |
38
+ - op: replace
39
+ path: /data/HASURA_GRAPHQL_ENABLED_APIS
40
+ value: metadata,graphql
41
+ ```