@nitra/cursor 3.13.0 → 3.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.14.0] - 2026-06-02
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- k8s hasura_configmap: base/dev ConfigMap Hasura-Deployment має містити HASURA_GRAPHQL_ENABLED_APIS="metadata,graphql,pgdump" (точний рядок). Кожен не-base overlay (k8s/<env>/, env≠base/dev), що успадковує Hasura-base, має у kustomization.yaml перевизначати цей ключ до "metadata,graphql" (без pgdump) патчем JSON6902/Strategic Merge на ConfigMap — нова cross-file перевірка validateHasuraOverlayEnabledApisOverride
|
|
8
|
+
|
|
3
9
|
## [3.13.0] - 2026-06-02
|
|
4
10
|
|
|
5
11
|
### Changed
|
package/package.json
CHANGED
|
@@ -2358,6 +2358,7 @@ export const HASURA_REQUIRED_ENV_KEYS = [
|
|
|
2358
2358
|
'HASURA_GRAPHQL_ENABLE_RELAY',
|
|
2359
2359
|
'HASURA_GRAPHQL_ENABLE_TELEMETRY',
|
|
2360
2360
|
'HASURA_GRAPHQL_ENABLED_LOG_TYPES',
|
|
2361
|
+
'HASURA_GRAPHQL_ENABLED_APIS',
|
|
2361
2362
|
'HASURA_GRAPHQL_DISABLE_EVENTING'
|
|
2362
2363
|
]
|
|
2363
2364
|
|
|
@@ -4929,6 +4930,130 @@ async function validateProdKustomizationOverrides(root, yamlFilesAbs, fail, pass
|
|
|
4929
4930
|
}
|
|
4930
4931
|
}
|
|
4931
4932
|
|
|
4933
|
+
/** Очікуване `HASURA_GRAPHQL_ENABLED_APIS` у non-base/dev overlay (без `pgdump` — він лише для base/dev). */
|
|
4934
|
+
const HASURA_OVERLAY_ENABLED_APIS = 'metadata,graphql'
|
|
4935
|
+
|
|
4936
|
+
/** JSON-Pointer ключа `HASURA_GRAPHQL_ENABLED_APIS` у `data` ConfigMap (для JSON6902-патчів). */
|
|
4937
|
+
const HASURA_ENABLED_APIS_DATA_POINTER = '/data/HASURA_GRAPHQL_ENABLED_APIS'
|
|
4938
|
+
|
|
4939
|
+
/**
|
|
4940
|
+
* Чи дерево kustomization (`resources` / `bases` / `components` / `crds`, рекурсивно) містить
|
|
4941
|
+
* **Hasura-Deployment** у шарі base (образ `hasura/graphql-engine`). Маркер того, що overlay успадковує
|
|
4942
|
+
* Hasura-ConfigMap з pgdump-значенням `ENABLED_APIS` і має його перевизначити.
|
|
4943
|
+
* @param {string} kustAbs kustomization.yaml
|
|
4944
|
+
* @param {string} rootNorm нормалізований корінь репо
|
|
4945
|
+
* @returns {Promise<boolean>} true, якщо в успадкованому base є Hasura-Deployment
|
|
4946
|
+
*/
|
|
4947
|
+
export async function kustomizationTreeHasHasuraDeployment(kustAbs, rootNorm) {
|
|
4948
|
+
const visited = new Set()
|
|
4949
|
+
const paths = await collectYamlAbsPathsFromKustomizationTree(kustAbs, rootNorm, visited)
|
|
4950
|
+
const rootResolved = resolve(rootNorm)
|
|
4951
|
+
for (const abs of paths) {
|
|
4952
|
+
const rel = (relative(rootResolved, abs) || '').replaceAll('\\', '/')
|
|
4953
|
+
if (!isK8sYamlUnderBaseDirectory(rel)) continue
|
|
4954
|
+
const roots = await readK8sYamlDocumentRootsForInventory(abs)
|
|
4955
|
+
if (roots.some(o => isHasuraDeploymentManifest(o))) return true
|
|
4956
|
+
}
|
|
4957
|
+
return false
|
|
4958
|
+
}
|
|
4959
|
+
|
|
4960
|
+
/**
|
|
4961
|
+
* Значення, яке inline-`patch` присвоює `data.HASURA_GRAPHQL_ENABLED_APIS`. Підтримка двох форматів:
|
|
4962
|
+
* **JSON6902** (`op` add/replace на `/data/HASURA_GRAPHQL_ENABLED_APIS`) і **Strategic Merge**
|
|
4963
|
+
* (`data.HASURA_GRAPHQL_ENABLED_APIS`). Зовнішні patch-файли (`patches[].path`) не охоплені — Plan B trade-off.
|
|
4964
|
+
* @param {string} patchText вміст поля `patch`
|
|
4965
|
+
* @returns {string | null} присвоєне значення (рядок) або null, якщо patch не чіпає цей ключ
|
|
4966
|
+
*/
|
|
4967
|
+
export function enabledApisValueFromPatchText(patchText) {
|
|
4968
|
+
const t = typeof patchText === 'string' ? patchText.trim() : ''
|
|
4969
|
+
if (t === '') return null
|
|
4970
|
+
let parsed
|
|
4971
|
+
try {
|
|
4972
|
+
for (const d of parseAllDocuments(t)) {
|
|
4973
|
+
if (d.errors.length === 0) {
|
|
4974
|
+
parsed = d.toJSON()
|
|
4975
|
+
break
|
|
4976
|
+
}
|
|
4977
|
+
}
|
|
4978
|
+
} catch {
|
|
4979
|
+
return null
|
|
4980
|
+
}
|
|
4981
|
+
if (Array.isArray(parsed)) {
|
|
4982
|
+
for (const item of parsed) {
|
|
4983
|
+
if (item === null || typeof item !== 'object' || Array.isArray(item)) continue
|
|
4984
|
+
const rec = /** @type {Record<string, unknown>} */ (item)
|
|
4985
|
+
const op = typeof rec.op === 'string' ? rec.op.trim().toLowerCase() : ''
|
|
4986
|
+
const path = typeof rec.path === 'string' ? normalizeJsonPatchPath(rec.path) : ''
|
|
4987
|
+
if ((op === 'add' || op === 'replace') && path === HASURA_ENABLED_APIS_DATA_POINTER) {
|
|
4988
|
+
return typeof rec.value === 'string' ? rec.value : JSON.stringify(rec.value)
|
|
4989
|
+
}
|
|
4990
|
+
}
|
|
4991
|
+
return null
|
|
4992
|
+
}
|
|
4993
|
+
if (parsed === null || typeof parsed !== 'object') return null
|
|
4994
|
+
const data = /** @type {Record<string, unknown>} */ (parsed).data
|
|
4995
|
+
if (data === null || typeof data !== 'object' || Array.isArray(data)) return null
|
|
4996
|
+
const d = /** @type {Record<string, unknown>} */ (data)
|
|
4997
|
+
if (!Object.hasOwn(d, 'HASURA_GRAPHQL_ENABLED_APIS')) return null
|
|
4998
|
+
const v = d.HASURA_GRAPHQL_ENABLED_APIS
|
|
4999
|
+
return typeof v === 'string' ? v : JSON.stringify(v)
|
|
5000
|
+
}
|
|
5001
|
+
|
|
5002
|
+
/**
|
|
5003
|
+
* Значення, яке `patches[]` kustomization присвоюють `data.HASURA_GRAPHQL_ENABLED_APIS` на цілі **ConfigMap**.
|
|
5004
|
+
* Повертає значення першого patch-а, що чіпає цей ключ, або null, якщо такого немає.
|
|
5005
|
+
* @param {Record<string, unknown>} kust об'єкт kustomization.yaml
|
|
5006
|
+
* @returns {string | null} присвоєне значення або null
|
|
5007
|
+
*/
|
|
5008
|
+
export function hasuraEnabledApisOverrideValue(kust) {
|
|
5009
|
+
const patches = kust.patches
|
|
5010
|
+
if (!Array.isArray(patches)) return null
|
|
5011
|
+
for (const p of patches) {
|
|
5012
|
+
if (p === null || typeof p !== 'object' || Array.isArray(p)) continue
|
|
5013
|
+
const pr = /** @type {Record<string, unknown>} */ (p)
|
|
5014
|
+
if (typeof pr.patch !== 'string') continue
|
|
5015
|
+
if (resolvePatchTargetKind(pr) !== 'ConfigMap') continue
|
|
5016
|
+
const v = enabledApisValueFromPatchText(pr.patch)
|
|
5017
|
+
if (v !== null) return v
|
|
5018
|
+
}
|
|
5019
|
+
return null
|
|
5020
|
+
}
|
|
5021
|
+
|
|
5022
|
+
/**
|
|
5023
|
+
* Для кожного **non-base/dev** overlay `kustomization.yaml`, що успадковує Hasura-base (Deployment з
|
|
5024
|
+
* `hasura/graphql-engine`), вимагає у `patches[]` перевизначення **`data.HASURA_GRAPHQL_ENABLED_APIS`**
|
|
5025
|
+
* до **`"metadata,graphql"`** (pgdump лишається строго для base/dev) (k8s.mdc). `kind: Component`
|
|
5026
|
+
* пропускається (env-неутральне джерело, не overlay).
|
|
5027
|
+
* @param {string} root корінь репозиторію
|
|
5028
|
+
* @param {string[]} yamlFilesAbs yaml під k8s
|
|
5029
|
+
* @param {(msg: string) => void} fail callback при помилці
|
|
5030
|
+
* @param {(msg: string) => void} passFn callback при успіху
|
|
5031
|
+
*/
|
|
5032
|
+
async function validateHasuraOverlayEnabledApisOverride(root, yamlFilesAbs, fail, passFn) {
|
|
5033
|
+
const rootNorm = resolve(root)
|
|
5034
|
+
const kustFiles = yamlFilesAbs.filter(abs => basename(abs) === 'kustomization.yaml')
|
|
5035
|
+
for (const kustAbs of kustFiles) {
|
|
5036
|
+
const rel = (relative(rootNorm, kustAbs) || kustAbs).replaceAll('\\', '/')
|
|
5037
|
+
const segment = k8sEnvSegmentFromRelPath(rel)
|
|
5038
|
+
if (segment === null || segment === 'base' || segment === 'dev') continue
|
|
5039
|
+
const kust = await readFirstYamlObject(kustAbs)
|
|
5040
|
+
if (kust === null || kust.kind === 'Component') continue
|
|
5041
|
+
if (!(await kustomizationTreeHasHasuraDeployment(kustAbs, rootNorm))) continue
|
|
5042
|
+
const value = hasuraEnabledApisOverrideValue(kust)
|
|
5043
|
+
if (value === HASURA_OVERLAY_ENABLED_APIS) {
|
|
5044
|
+
passFn(`${rel}: overlay '${segment}' перевизначає HASURA_GRAPHQL_ENABLED_APIS="${HASURA_OVERLAY_ENABLED_APIS}" (k8s.mdc)`)
|
|
5045
|
+
} else if (value === null) {
|
|
5046
|
+
fail(
|
|
5047
|
+
`${rel}: overlay '${segment}' має у patches[] перевизначати data.HASURA_GRAPHQL_ENABLED_APIS до "${HASURA_OVERLAY_ENABLED_APIS}" (pgdump лише для base/dev) (k8s.mdc)`
|
|
5048
|
+
)
|
|
5049
|
+
} else {
|
|
5050
|
+
fail(
|
|
5051
|
+
`${rel}: overlay '${segment}' patch data.HASURA_GRAPHQL_ENABLED_APIS має бути "${HASURA_OVERLAY_ENABLED_APIS}" (зараз: ${JSON.stringify(value)}) (k8s.mdc)`
|
|
5052
|
+
)
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
|
|
4932
5057
|
/**
|
|
4933
5058
|
* Шукає HPA за `scaleTargetRef.name` серед документів.
|
|
4934
5059
|
* @param {Record<string, unknown>[]} hpaDocs масив HPA-документів
|
|
@@ -6626,5 +6751,7 @@ export async function check(cwd = process.cwd()) {
|
|
|
6626
6751
|
|
|
6627
6752
|
await validateProdKustomizationOverrides(root, yamlFiles, fail, pass)
|
|
6628
6753
|
|
|
6754
|
+
await validateHasuraOverlayEnabledApisOverride(root, yamlFiles, fail, pass)
|
|
6755
|
+
|
|
6629
6756
|
return reporter.getExitCode()
|
|
6630
6757
|
}
|
package/rules/k8s/k8s.mdc
CHANGED
|
@@ -303,6 +303,7 @@ spec:
|
|
|
303
303
|
- **`HASURA_GRAPHQL_ENABLE_RELAY`** зі значенням **`"false"`**;
|
|
304
304
|
- **`HASURA_GRAPHQL_ENABLE_TELEMETRY`** зі значенням **`"false"`**;
|
|
305
305
|
- **`HASURA_GRAPHQL_ENABLED_LOG_TYPES`** зі значенням **`"startup,http-log"`** (точний рядок);
|
|
306
|
+
- **`HASURA_GRAPHQL_ENABLED_APIS`** зі значенням **`"metadata,graphql,pgdump"`** (точний рядок) — **значення для base/dev**;
|
|
306
307
|
- **`HASURA_GRAPHQL_DISABLE_EVENTING`** — ключ обов'язковий, значення довільне (за замовчуванням **`"true"`**).
|
|
307
308
|
|
|
308
309
|
Точні умови перевірки — rego-пакет **`k8s.hasura_configmap`** (cross-file прив'язка ConfigMap↔Deployment — у `rules/k8s/js/manifests.mjs`).
|
|
@@ -313,9 +314,25 @@ data:
|
|
|
313
314
|
HASURA_GRAPHQL_ENABLE_RELAY: 'false'
|
|
314
315
|
HASURA_GRAPHQL_ENABLE_TELEMETRY: 'false'
|
|
315
316
|
HASURA_GRAPHQL_ENABLED_LOG_TYPES: 'startup,http-log'
|
|
317
|
+
HASURA_GRAPHQL_ENABLED_APIS: 'metadata,graphql,pgdump'
|
|
316
318
|
HASURA_GRAPHQL_DISABLE_EVENTING: 'true'
|
|
317
319
|
```
|
|
318
320
|
|
|
321
|
+
### `HASURA_GRAPHQL_ENABLED_APIS` поза base/dev
|
|
322
|
+
|
|
323
|
+
`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` пропускається.
|
|
324
|
+
|
|
325
|
+
```yaml title="k8s/prod/kustomization.yaml"
|
|
326
|
+
patches:
|
|
327
|
+
- target:
|
|
328
|
+
kind: ConfigMap
|
|
329
|
+
name: db-h
|
|
330
|
+
patch: |
|
|
331
|
+
- op: replace
|
|
332
|
+
path: /data/HASURA_GRAPHQL_ENABLED_APIS
|
|
333
|
+
value: metadata,graphql
|
|
334
|
+
```
|
|
335
|
+
|
|
319
336
|
## Kustomize: структура каталогів (`base` / overlays)
|
|
320
337
|
|
|
321
338
|
Трансформуй дерева **`**/k8s`**, щоб **винести спільне** через [Kustomize](https://kustomize.io/): один канонічний **`base`** і тонкі **overlays** для інших середовищ.
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
# "HASURA_GRAPHQL_ENABLE_RELAY" → "false"
|
|
7
7
|
# "HASURA_GRAPHQL_ENABLE_TELEMETRY" → "false"
|
|
8
8
|
# "HASURA_GRAPHQL_ENABLED_LOG_TYPES" → "startup,http-log" (точний рядок)
|
|
9
|
+
# "HASURA_GRAPHQL_ENABLED_APIS" → "metadata,graphql,pgdump" (точний рядок;
|
|
10
|
+
# це значення для base/dev. Не-base overlay-и мають зводити його до "metadata,graphql"
|
|
11
|
+
# патчем у kustomization.yaml — перевіряє JS `validateHasuraOverlayEnabledApisOverride`)
|
|
9
12
|
# "HASURA_GRAPHQL_DISABLE_EVENTING" → null (ключ обов'язковий,
|
|
10
13
|
# значення довільне; за замовчуванням рекомендовано "true")
|
|
11
14
|
#
|
|
@@ -39,6 +42,7 @@ required_env := {
|
|
|
39
42
|
"HASURA_GRAPHQL_ENABLE_RELAY": "false",
|
|
40
43
|
"HASURA_GRAPHQL_ENABLE_TELEMETRY": "false",
|
|
41
44
|
"HASURA_GRAPHQL_ENABLED_LOG_TYPES": "startup,http-log",
|
|
45
|
+
"HASURA_GRAPHQL_ENABLED_APIS": "metadata,graphql,pgdump",
|
|
42
46
|
"HASURA_GRAPHQL_DISABLE_EVENTING": null,
|
|
43
47
|
}
|
|
44
48
|
|