@nitra/cursor 1.8.123 → 1.8.124

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/mdc/abie.mdc CHANGED
@@ -4,7 +4,7 @@ alwaysApply: true
4
4
  version: '1.15'
5
5
  ---
6
6
 
7
- Правило **abie** для споживачів **@nitra/cursor**: **k8s** (Deployment + **HealthCheckPolicy** у **`hc.yaml`**, overlay **ua** / **ru** — **nodeSelector**, **HTTPRoute** (будь-який непорожній **`target.name`**, для спільних сервісів **`auth-run-hl`** / **`file-link-hl`** — **`namespace: dev`** у base та patch **`…/backendRefs/…/namespace`** у **ua** / **ru**), у overlay **ru** — кожен **Service** (у т. ч. **headless** / **`-hl`**) → **`spec.type: NodePort`** через **JSON6902** у **`kustomization.yaml`**, видалення **HealthCheckPolicy** у **ru**), гілки **dev**, **ua**, **ru** у **clean-merged-branch**, а також заборона артефактів **Firebase Hosting** у корені репозиторію.
7
+ Правило **abie** для споживачів **@nitra/cursor**: **k8s** (Deployment + **HealthCheckPolicy** у **`hc.yaml`**, overlay **ua** / **ru** — **nodeSelector**, **HTTPRoute** (будь-який непорожній **`target.name`**, для спільних сервісів **`auth-run-hl`** / **`file-link-hl`** — **`namespace: dev`** у base та patch **`…/backendRefs/…/namespace`** у **ua** / **ru**), у overlay **ru** — кожен **Service** (у т. ч. **headless** / **`-hl`**) → **`spec.type: NodePort`** через **JSON6902** у **`kustomization.yaml`**, видалення **HealthCheckPolicy** у **ru**), гілки **dev**, **ua**, **ru** у **clean-merged-branch**, а також заборона тримати артефакти **Firebase Hosting** у **підкаталогах першого рівня** (безпосередні діти кореня репозиторію; у самому корені ці імена не вимагаються до видалення).
8
8
 
9
9
  **`npx @nitra/cursor check abie`** виконується лише якщо в **`.n-cursor.json`** у **`rules`** є **`abie`** — інакше вихід **0** без зауважень.
10
10
 
@@ -334,7 +334,7 @@ spec:
334
334
 
335
335
  ## Firebase Hosting
336
336
 
337
- У корені репозиторію не тримати конфіг і кеш **Firebase Hosting**: видали **`.firebaserc`**, **`firebase.json`** та каталог **`.firebase/`**, якщо вони є.
337
+ У **кожному** підкаталозі, що лежить **безпосередньо** в корені репозиторію, не тримати конфіг і кеш **Firebase Hosting**: у таких каталогах не повинно бути **`.firebaserc`**, **`firebase.json`** та каталогу **`.firebase/`** **самому** корені репозиторію ці імена перевіркою abie **не** розглядаються; `node_modules` / `.git` зі скану вилучаються).
338
338
 
339
339
  ## Git branches
340
340
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitra/cursor",
3
- "version": "1.8.123",
3
+ "version": "1.8.124",
4
4
  "description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
5
5
  "keywords": [
6
6
  "cli",
@@ -8,7 +8,8 @@
8
8
  * **`phpdocker-io/github-actions-delete-abandoned-branches`** у **`with.ignore_branches`** мають бути
9
9
  * **dev**, **ua** та **ru** (разом з іншими гілками, якщо потрібно).
10
10
  *
11
- * **Firebase Hosting:** у корені репозиторію не має бути **`.firebaserc`**, **`firebase.json`** та каталогу **`.firebase/`**.
11
+ * **Firebase Hosting:** у **підкаталогах першого рівня** (безпосередні діти кореня репозиторію; `node_modules` / `.git` пропускаються) не має бути
12
+ * **`.firebaserc`**, **`firebase.json`** та каталогу **`.firebase/`**; у **самому** корені репозиторію ці імена не перевіряються.
12
13
  *
13
14
  * **k8s:** якщо під деревом із сегментом **`k8s`** є YAML з **`kind: Deployment`**, у тій самій директорії
14
15
  * має існувати **`hc.yaml`** із **`HealthCheckPolicy`** (**`networking.gke.io/v1`**), modeline **`$schema`**
@@ -38,7 +39,7 @@
38
39
  * у файлі **`k8s/ru/kustomization.yaml`** того ж пакета (overlay середовища **ru**) — inline **JSON6902** на **`kind: Service`** з тим самим **`target.name`**: **`path: /spec/type`**, **`value: NodePort`**; якщо в base було **`spec.clusterIP: None`** — **`op: remove`** для **`/spec/clusterIP`**; якщо в base **явно** задано **`spec.clusterIPs`** — також **`remove`** для **`/spec/clusterIPs`** (інакше **API** може залишити **`None`** для **NodePort**; без ключа **`clusterIPs`** у base **`remove`** на **`/spec/clusterIPs`** ламає **`kubectl kustomize`**).
39
40
  */
40
41
  import { existsSync } from 'node:fs'
41
- import { readFile } from 'node:fs/promises'
42
+ import { readdir, readFile } from 'node:fs/promises'
42
43
  import { dirname, join, relative } from 'node:path'
43
44
 
44
45
  import { parseAllDocuments } from 'yaml'
@@ -50,6 +51,9 @@ import { walkDir } from './utils/walkDir.mjs'
50
51
 
51
52
  const CONFIG_FILE = '.n-cursor.json'
52
53
 
54
+ /** Каталоги-діти в корені, які пропускаються при скануванні на артефакти Firebase Hosting (abie). */
55
+ const ABIE_FIREBASE_HOSTING_SCAN_SKIP_TOP_DIR_NAMES = new Set(['.git', 'node_modules'])
56
+
53
57
  /** Маркер у kustomization.yaml: якщо зустрічається у файлі — для overlay ru у patch HTTPRoute потрібна анотація gwin…websocket. */
54
58
  const HASURA_JWT_SECRET_IN_KUSTOMIZATION = 'HASURA_GRAPHQL_JWT_SECRET'
55
59
 
@@ -1679,27 +1683,46 @@ async function ensureUaRuAbieHttpRoutePatches(root, yamlFilesAbs, fail, passFn)
1679
1683
  }
1680
1684
 
1681
1685
  /**
1682
- * Перевіряє відсутність артефактів Firebase Hosting у корені репозиторію (abie.mdc).
1686
+ * Перевіряє відсутність артефактів Firebase Hosting у **кожному** **підкаталозі першого рівня** від кореня
1687
+ * (не в самому корені репозиторію) — abie.mdc. Каталоги **`.git`** і **`node_modules`** у скануванні пропускаються.
1688
+ *
1683
1689
  * @param {string} root корінь репозиторію
1684
1690
  * @param {(msg: string) => void} passFn успішне повідомлення
1685
1691
  * @param {(msg: string) => void} failFn повідомлення про порушення
1686
- * @returns {void}
1687
- */
1688
- function ensureNoFirebaseHostingArtifacts(root, passFn, failFn) {
1689
- for (const name of ['.firebaserc', 'firebase.json']) {
1690
- const abs = join(root, name)
1691
- if (existsSync(abs)) {
1692
- failFn(`Знайдено заборонений файл Firebase Hosting: ${name} видали його (abie.mdc)`)
1693
- } else {
1694
- passFn(`Немає ${name}`)
1692
+ * @returns {Promise<void>}
1693
+ */
1694
+ async function ensureNoFirebaseHostingArtifacts(root, passFn, failFn) {
1695
+ let entries
1696
+ try {
1697
+ entries = await readdir(root, { withFileTypes: true })
1698
+ } catch (error) {
1699
+ const msg = error instanceof Error ? error.message : String(error)
1700
+ failFn(`Не вдалося прочитати ${root} для перевірки Firebase Hosting: ${msg} (abie.mdc)`)
1701
+ return
1702
+ }
1703
+ const topDirs = entries.filter(
1704
+ e => e.isDirectory() && !ABIE_FIREBASE_HOSTING_SCAN_SKIP_TOP_DIR_NAMES.has(e.name)
1705
+ )
1706
+ let hasViolation = false
1707
+ for (const e of topDirs) {
1708
+ for (const name of ['.firebaserc', 'firebase.json']) {
1709
+ const rel = join(e.name, name).replaceAll('\\', '/')
1710
+ if (existsSync(join(root, e.name, name))) {
1711
+ failFn(`Знайдено заборонений файл Firebase Hosting: ${rel} — видали його (abie.mdc)`)
1712
+ hasViolation = true
1713
+ }
1714
+ }
1715
+ if (existsSync(join(root, e.name, '.firebase'))) {
1716
+ failFn(`Знайдено заборонену директорію: ${e.name}/.firebase/ — видали її (abie.mdc)`)
1717
+ hasViolation = true
1695
1718
  }
1696
1719
  }
1697
- const firebaseDir = join(root, '.firebase')
1698
- if (existsSync(firebaseDir)) {
1699
- failFn('Знайдено директорію .firebase — видали її (abie.mdc)')
1700
- } else {
1701
- passFn('Немає .firebase/')
1720
+ if (hasViolation) {
1721
+ return
1702
1722
  }
1723
+ passFn(
1724
+ 'Підкаталоги кореня (1-й рівень, без .git/node_modules): артефактів Firebase Hosting не знайдено (abie.mdc)'
1725
+ )
1703
1726
  }
1704
1727
 
1705
1728
  /**
@@ -2075,7 +2098,7 @@ export async function check() {
2075
2098
  }
2076
2099
 
2077
2100
  pass('Правило abie увімкнено — виконуємо перевірки')
2078
- ensureNoFirebaseHostingArtifacts(root, pass, fail)
2101
+ await ensureNoFirebaseHostingArtifacts(root, pass, fail)
2079
2102
  await checkCleanMergedBranch(root, pass, fail)
2080
2103
 
2081
2104
  const yamlFiles = await findK8sYamlFiles(root)