@nitra/cursor 12.8.6 → 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 (187) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +1 -1
  3. package/rules/adr/js/hooks.mdc +32 -0
  4. package/rules/adr/js/madr_format.mdc +96 -0
  5. package/rules/adr/js/settings_policy.mdc +34 -0
  6. package/rules/adr/main.mdc +13 -95
  7. package/rules/bun/js/bunfig.mdc +12 -0
  8. package/rules/bun/js/layout.mdc +60 -0
  9. package/rules/bun/js/lint.mdc +9 -0
  10. package/rules/bun/js/package_json.mdc +19 -0
  11. package/rules/bun/main.mdc +9 -61
  12. package/rules/capacitor/js/ios_spm.mdc +69 -0
  13. package/rules/capacitor/js/version.mdc +29 -0
  14. package/rules/capacitor/main.mdc +8 -22
  15. package/rules/changelog/js/agent-workflow.mdc +15 -0
  16. package/rules/changelog/js/changelog-format.mdc +33 -0
  17. package/rules/changelog/js/comparison-models.mdc +40 -0
  18. package/rules/changelog/main.mdc +4 -98
  19. package/rules/ci4/js/marksman_config.mdc +31 -0
  20. package/rules/ci4/js/vscode_extensions.mdc +33 -0
  21. package/rules/ci4/main.mdc +14 -14
  22. package/rules/docker/js/compile.mdc +44 -0
  23. package/rules/docker/js/hadolint.mdc +50 -0
  24. package/rules/docker/js/mirror.mdc +13 -0
  25. package/rules/docker/js/multistage.mdc +13 -0
  26. package/rules/docker/js/native-addon.mdc +43 -0
  27. package/rules/docker/js/nginx-tag.mdc +7 -0
  28. package/rules/docker/js/nginx-user.mdc +37 -0
  29. package/rules/docker/js/non-root.mdc +39 -0
  30. package/rules/docker/main.mdc +15 -196
  31. package/rules/ga/js/lint_toolchain.mdc +15 -0
  32. package/rules/ga/js/required_workflows.mdc +35 -0
  33. package/rules/ga/js/vscode.mdc +17 -0
  34. package/rules/ga/js/workflow_common.mdc +108 -0
  35. package/rules/ga/js/workflows.mdc +32 -0
  36. package/rules/ga/js/zizmor.mdc +7 -0
  37. package/rules/ga/main.mdc +17 -125
  38. package/rules/graphql/js/tooling.mdc +13 -0
  39. package/rules/graphql/js/vscode_extensions.mdc +13 -0
  40. package/rules/graphql/main.mdc +3 -22
  41. package/rules/hasura/js/internal_urls.mdc +27 -0
  42. package/rules/hasura/js/migrations.mdc +13 -0
  43. package/rules/hasura/js/svc_hl.mdc +17 -0
  44. package/rules/hasura/main.mdc +8 -30
  45. package/rules/image-avif/js/avif_generation.mdc +26 -0
  46. package/rules/image-avif/js/package_json_optout.mdc +21 -0
  47. package/rules/image-avif/main.mdc +7 -34
  48. package/rules/image-compress/js/package_json.mdc +7 -0
  49. package/rules/image-compress/js/package_setup.mdc +13 -0
  50. package/rules/image-compress/main.mdc +4 -12
  51. package/rules/js/docs/index.md +3 -3
  52. package/rules/js/js/dep-policy.mdc +17 -0
  53. package/rules/js/js/eslint-config.mdc +28 -0
  54. package/rules/js/js/extensions.mdc +8 -0
  55. package/rules/js/js/file-extensions.mdc +12 -0
  56. package/rules/js/js/for-in.mdc +26 -0
  57. package/rules/js/js/jscpd.mdc +42 -0
  58. package/rules/js/js/knip.mdc +15 -0
  59. package/rules/js/js/lint-js-workflow.mdc +58 -0
  60. package/rules/js/js/oxlintrc.mdc +20 -0
  61. package/rules/js/js/package-json.mdc +31 -0
  62. package/rules/js/js/tests.mdc +9 -0
  63. package/rules/js/js/utils-lib-structure.mdc +15 -0
  64. package/rules/js/main.mdc +21 -214
  65. package/rules/js-bun-db/js/bun-sql-migration.mdc +15 -0
  66. package/rules/js-bun-db/js/connection.mdc +42 -0
  67. package/rules/js-bun-db/js/pg-format-identifiers.mdc +102 -0
  68. package/rules/js-bun-db/js/pg-format-shim.mdc +99 -0
  69. package/rules/js-bun-db/js/pg-leftover.mdc +27 -0
  70. package/rules/js-bun-db/js/pg-listen-notify.mdc +51 -0
  71. package/rules/js-bun-db/js/query-safety.mdc +117 -0
  72. package/rules/js-bun-db/js/sql-array.mdc +88 -0
  73. package/rules/js-bun-db/js/unsafe.mdc +65 -0
  74. package/rules/js-bun-db/main.mdc +15 -605
  75. package/rules/js-bun-redis/js/imports.mdc +47 -0
  76. package/rules/js-bun-redis/js/package_json.mdc +44 -0
  77. package/rules/js-bun-redis/main.mdc +3 -11
  78. package/rules/js-mssql/js/mssql-in-list.mdc +38 -0
  79. package/rules/js-mssql/js/mssql-pool.mdc +56 -0
  80. package/rules/js-mssql/js/mssql-query-template.mdc +33 -0
  81. package/rules/js-mssql/js/mssql-tvp.mdc +75 -0
  82. package/rules/js-mssql/js/mssql-version.mdc +7 -0
  83. package/rules/js-mssql/main.mdc +10 -198
  84. package/rules/js-run/js/check-env.mdc +35 -0
  85. package/rules/js-run/js/conn-aliases.mdc +109 -0
  86. package/rules/js-run/js/jsconfig.mdc +20 -0
  87. package/rules/js-run/js/otel-configmap.mdc +6 -0
  88. package/rules/js-run/js/pino.mdc +6 -0
  89. package/rules/js-run/js/project-structure.mdc +11 -0
  90. package/rules/js-run/js/runtime.mdc +14 -0
  91. package/rules/js-run/js/scope.mdc +11 -0
  92. package/rules/js-run/js/settimeout.mdc +11 -0
  93. package/rules/js-run/js/temporal.mdc +5 -0
  94. package/rules/js-run/main.mdc +16 -218
  95. package/rules/k8s/js/configmap.mdc +41 -0
  96. package/rules/k8s/js/deployment_resources.mdc +49 -0
  97. package/rules/k8s/js/hasura_httproute.mdc +91 -0
  98. package/rules/k8s/js/hpa_apiversion.mdc +27 -0
  99. package/rules/k8s/js/ingress_gateway.mdc +16 -0
  100. package/rules/k8s/js/kustomize_structure.mdc +144 -0
  101. package/rules/k8s/js/lint_k8s.mdc +72 -0
  102. package/rules/k8s/js/multidoc_yaml.mdc +5 -0
  103. package/rules/k8s/js/network_policy.mdc +136 -0
  104. package/rules/k8s/js/schema_modeline.mdc +57 -0
  105. package/rules/k8s/js/service.mdc +44 -0
  106. package/rules/k8s/js/topology_hpa_pdb.mdc +181 -0
  107. package/rules/k8s/main.mdc +30 -843
  108. package/rules/nginx-default-tpl/js/dockerfile.mdc +36 -0
  109. package/rules/nginx-default-tpl/js/http-route.mdc +41 -0
  110. package/rules/nginx-default-tpl/js/ini-keys.mdc +21 -0
  111. package/rules/nginx-default-tpl/js/template-structure.mdc +86 -0
  112. package/rules/nginx-default-tpl/js/vscode.mdc +37 -0
  113. package/rules/nginx-default-tpl/main.mdc +6 -112
  114. package/rules/npm-module/js/docs/index.md +5 -5
  115. package/rules/npm-module/js/docs/rule_meta.md +6 -6
  116. package/rules/npm-module/js/docs/skill_meta.md +8 -8
  117. package/rules/npm-module/js/header_doc_pointer.mdc +18 -0
  118. package/rules/npm-module/js/package_structure.mdc +62 -0
  119. package/rules/npm-module/js/rule_meta.mdc +11 -0
  120. package/rules/npm-module/js/skill_meta.mdc +11 -0
  121. package/rules/npm-module/main.mdc +10 -55
  122. package/rules/php/js/lint_php_yml.mdc +12 -0
  123. package/rules/php/js/tooling.mdc +66 -0
  124. package/rules/php/main.mdc +7 -66
  125. package/rules/python/js/lint_python_yml.mdc +23 -0
  126. package/rules/python/js/pyproject_toml.mdc +32 -0
  127. package/rules/python/js/tooling.mdc +23 -0
  128. package/rules/python/main.mdc +9 -33
  129. package/rules/rego/js/rego-lint.mdc +31 -0
  130. package/rules/rego/js/vscode_extensions.mdc +11 -0
  131. package/rules/rego/js/vscode_settings.mdc +13 -0
  132. package/rules/rego/main.mdc +8 -24
  133. package/rules/rust/js/coverage.mdc +28 -0
  134. package/rules/rust/js/lint.mdc +22 -0
  135. package/rules/rust/js/tauri_composition.mdc +8 -0
  136. package/rules/rust/js/vscode_extensions.mdc +12 -0
  137. package/rules/rust/main.mdc +8 -38
  138. package/rules/security/js/rego_policies.mdc +15 -0
  139. package/rules/security/js/sample_secret.mdc +19 -0
  140. package/rules/security/js/trufflehog.mdc +21 -0
  141. package/rules/security/main.mdc +7 -35
  142. package/rules/style/js/admin-table.mdc +88 -0
  143. package/rules/style/js/colors.mdc +21 -0
  144. package/rules/style/js/gap.mdc +22 -0
  145. package/rules/style/js/quasar-fixes.mdc +32 -0
  146. package/rules/style/js/quasar.mdc +7 -0
  147. package/rules/style/js/tooling.mdc +85 -0
  148. package/rules/style/main.mdc +13 -253
  149. package/rules/tauri/js/cargo_mutants_config.mdc +39 -0
  150. package/rules/tauri/js/tool_surface.mdc +21 -0
  151. package/rules/tauri/js/tooling.mdc +25 -0
  152. package/rules/tauri/main.mdc +8 -78
  153. package/rules/test/js/cargo_mutants_config.mdc +18 -0
  154. package/rules/test/js/docs/index.md +7 -7
  155. package/rules/test/js/location.mdc +52 -0
  156. package/rules/test/js/no-console-store-restore.mdc +11 -0
  157. package/rules/test/js/no-process-chdir.mdc +15 -0
  158. package/rules/test/js/no-relative-fs-path.mdc +22 -0
  159. package/rules/test/js/sandbox-aware-test.mdc +28 -0
  160. package/rules/test/js/stryker_config.mdc +26 -0
  161. package/rules/test/js/vitest-config-pool-forks.mdc +33 -0
  162. package/rules/test/main.mdc +18 -184
  163. package/rules/text/js/ci-lint-text.mdc +15 -0
  164. package/rules/text/js/cspell.mdc +81 -0
  165. package/rules/text/js/dotenv-linter.mdc +16 -0
  166. package/rules/text/js/forbidden-prettier.mdc +13 -0
  167. package/rules/text/js/markdownlint.mdc +25 -0
  168. package/rules/text/js/oxfmt.mdc +35 -0
  169. package/rules/text/js/package-json.mdc +26 -0
  170. package/rules/text/js/shellcheck.mdc +18 -0
  171. package/rules/text/js/v8r.mdc +23 -0
  172. package/rules/text/js/vscode.mdc +86 -0
  173. package/rules/text/main.mdc +20 -237
  174. package/rules/vue/js/composition-api.mdc +82 -0
  175. package/rules/vue/js/nheader-layout.mdc +171 -0
  176. package/rules/vue/js/node-imports.mdc +25 -0
  177. package/rules/vue/js/quasar-ui.mdc +32 -0
  178. package/rules/vue/js/structure.mdc +101 -0
  179. package/rules/vue/js/testing.mdc +32 -0
  180. package/rules/vue/js/tfm-translations.mdc +26 -0
  181. package/rules/vue/js/vite-config.mdc +126 -0
  182. package/rules/vue/js/vite-env.mdc +55 -0
  183. package/rules/vue/js/vue-imports.mdc +25 -0
  184. package/rules/vue/main.mdc +16 -640
  185. package/scripts/docs/index.md +16 -16
  186. package/scripts/lib/docs/index.md +36 -36
  187. 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,32 @@ 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`).
40
-
41
- ## Структура проекту
42
-
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-барель.
34
+ - `js_run.package_json` заборонені `dependencies`/`devDependencies` (`bunyan`, `@nitra/bunyan`) і заборонені патерни у `scripts` (`node`, `env $(cat …) bun`)
35
+ - `js_run.jsconfig` — відповідність `jsconfig.json` канону (`NodeNext`, `include: src/**/*`)
36
+ - `js_run.configmap` — наявність `service.name=` і `service.namespace=` у `OTEL_RESOURCE_ATTRIBUTES` в `k8s/base/configmap.yaml`
@@ -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
+ ```
@@ -0,0 +1,49 @@
1
+ ## Deployment: `resources.requests` (CPU і memory)
2
+
3
+ У кожному контейнері **`Deployment`** обов'язкові **`resources.requests.cpu`** і **`resources.requests.memory`** (непорожні скаляри Kubernetes Quantity).
4
+
5
+ ### Шар **`…/k8s/…/base/…`** (dev / щільний packing)
6
+
7
+ У **всіх** `Deployment` у файлах під **`…/k8s/…/base/…`** значення **жорстко фіксовані** (для **cpu** допускається число **`0.02`** у YAML):
8
+
9
+ ```yaml
10
+ resources:
11
+ requests:
12
+ cpu: '0.02'
13
+ memory: '128Mi'
14
+ ```
15
+
16
+ **HPA і PDB у base не тримаємо**: ні локальних `hpa.yaml` / `pdb.yaml` поруч із workload-manifest-файлами, ні через `resources` / `components` / `bases`. Канон — sibling каталог **`components/`** (Kustomize Component) поруч з `base/`, який підключають лише прод-overlays. **NetworkPolicy** — навпаки: **обов'язковий і у `base/`**, у вигляді `base/networkpolicy.yaml` підключений через `base/kustomization.yaml` `resources:`.
17
+
18
+ ### Поза base (оверлеї, окремі каталоги)
19
+
20
+ Якщо ще не підібрано власні ліміти під сервіс, орієнтир для **`requests`**:
21
+
22
+ ```yaml
23
+ resources:
24
+ requests:
25
+ cpu: '0.5'
26
+ memory: '512Mi'
27
+ ```
28
+
29
+ У прод-оверлеях підіймай **`cpu` / `memory`** до реального споживання через **`patches`**. **`check k8s`** не вимагає саме **`0.5` / `512Mi`** поза base — лише непорожні **`requests.cpu`** і **`requests.memory`**.
30
+
31
+ ```yaml title="k8s/prod/kustomization.yaml (фрагмент)"
32
+ patches:
33
+ - target:
34
+ kind: Deployment
35
+ name: backend-api
36
+ patch: |-
37
+ - op: replace
38
+ path: /spec/template/spec/containers/0/resources/requests/cpu
39
+ value: '500m'
40
+ - op: replace
41
+ path: /spec/template/spec/containers/0/resources/requests/memory
42
+ value: 1Gi
43
+ ```
44
+
45
+ ### Образ `hasura/graphql-engine`
46
+
47
+ Образ **`hasura/graphql-engine`**: дозволений лише канонічний тег зі списку **`allowed_hasura_images`** у rego-пакеті **`k8s.manifest`** (`policy/manifest/manifest.rego` — єдине джерело істини; допускається префікс **`docker.io/`**); решта — помилка **check k8s**.
48
+
49
+ Поле **`imagePullPolicy`** скрипт **не** перевіряє.
@@ -0,0 +1,91 @@
1
+ ## HTTPRoute для Deployment з `hasura/graphql-engine`
2
+
3
+ **Прив'язка:** **check k8s** вважає **HTTPRoute** Hasura-маршрутом, якщо в **тому самому каталозі** є **`Deployment`** з образом **`hasura/graphql-engine`**, а його **`metadata.name`** збігається з **`metadata.name`** цього **`HTTPRoute`**.
4
+
5
+ **Префікс параметризовано:** **`<prefix>`** — рядок перед **`/ql`** у першому Hasura-правилі (**`Exact <prefix>/ql`**). Може бути порожнім (**`<prefix>`** = **``**, шлях **`/ql`**) або непорожнім (наприклад **`<prefix>`** = **`/notify`**, шлях **`/notify/ql`**). Усі інші Hasura-правила цього **HTTPRoute** мають містити той самий **`<prefix>`**.
6
+
7
+ **Канон — 4 правила у цьому порядку** (додаткові правила поверх канону дозволені):
8
+
9
+ 1. **`Exact <prefix>/ql`** → **`RequestRedirect`** **`ReplaceFullPath <prefix>/ql/console`** **`statusCode: 302`**.
10
+ 2. **`Exact <prefix>/ql/`** → те саме (редирект на **`<prefix>/ql/console`** 302).
11
+ 3. **`PathPrefix <prefix>/ql`** → **`URLRewrite`** **`ReplacePrefixMatch /`**, один **`backendRef`** на headless **Service** (**`-hl`**).
12
+ 4. **WebSocket:** **`PathPrefix <prefix>/ql`** + header **`Upgrade: websocket`** → **`URLRewrite`** **`ReplacePrefixMatch /`** + **`RequestHeaderModifier`** **`remove: [Authorization]`** (авторизація для WebSocket іде всередині messages). Той самий **`backendRef`**.
13
+
14
+ **`parentRefs`**, **`hostnames`**, **`metadata.namespace`** / **`name`** підлаштуй під середовище. У **`backendRefs.name`** вказуй **headless** **Service** з суфіксом **`-hl`**; у прикладі **`db-h-hl`** заміни на фактичне ім'я.
15
+
16
+ ```yaml
17
+ # yaml-language-server: $schema=https://datreeio.github.io/CRDs-catalog/gateway.networking.k8s.io/httproute_v1beta1.json
18
+ apiVersion: gateway.networking.k8s.io/v1
19
+ kind: HTTPRoute
20
+ metadata:
21
+ name: db-h
22
+ namespace: dev
23
+ spec:
24
+ parentRefs:
25
+ - group: gateway.networking.k8s.io
26
+ kind: Gateway
27
+ name: gw
28
+ namespace: dev
29
+ sectionName: https
30
+ hostnames:
31
+ - aiml.live
32
+ rules:
33
+ - matches:
34
+ - path:
35
+ type: Exact
36
+ value: /ql
37
+ filters:
38
+ - type: RequestRedirect
39
+ requestRedirect:
40
+ path:
41
+ type: ReplaceFullPath
42
+ replaceFullPath: /ql/console
43
+ statusCode: 302
44
+ - matches:
45
+ - path:
46
+ type: Exact
47
+ value: /ql/
48
+ filters:
49
+ - type: RequestRedirect
50
+ requestRedirect:
51
+ path:
52
+ type: ReplaceFullPath
53
+ replaceFullPath: /ql/console
54
+ statusCode: 302
55
+ - matches:
56
+ - path:
57
+ type: PathPrefix
58
+ value: /ql
59
+ filters:
60
+ - type: URLRewrite
61
+ urlRewrite:
62
+ path:
63
+ type: ReplacePrefixMatch
64
+ replacePrefixMatch: /
65
+ backendRefs:
66
+ - name: db-h-hl
67
+ port: 8080
68
+ # у websocket авторизація йде всередині messages
69
+ # Той самий URLRewrite, що й для HTTP: інакше бекенд бачить /ql/v1/graphql замість /v1/graphql
70
+ - matches:
71
+ - path:
72
+ type: PathPrefix
73
+ value: /ql
74
+ headers:
75
+ - type: Exact
76
+ name: Upgrade
77
+ value: websocket
78
+ filters:
79
+ - type: URLRewrite
80
+ urlRewrite:
81
+ path:
82
+ type: ReplacePrefixMatch
83
+ replacePrefixMatch: /
84
+ - type: RequestHeaderModifier
85
+ requestHeaderModifier:
86
+ remove:
87
+ - Authorization
88
+ backendRefs:
89
+ - name: db-h-hl
90
+ port: 8080
91
+ ```