@nitra/cursor 1.8.95 → 1.8.96

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/js-lint.mdc CHANGED
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  description: Перевірка JavaScript коду
3
3
  alwaysApply: true
4
- version: '1.11'
4
+ version: '1.13'
5
5
  ---
6
6
 
7
- **oxlint**, **ESLint**, **jscpd**. У скрипті **`lint-js`** і в CI — **`bunx oxlint`**, **`bunx eslint`**, **`bunx jscpd`** (у CI без **`--fix`** для oxlint/eslint — див. приклад workflow нижче). Без **prettier** і **@nitra/prettier-config**. Достатньо **`@nitra/eslint-config`** у devDependencies; пакети oxlint/eslint/jscpd не додавай без потреби монорепо.
7
+ **oxlint**, **ESLint**, **jscpd**. У скрипті **`lint-js`** і в CI — **`bunx oxlint`**, **`bunx eslint`**, **`bunx jscpd`** (у CI без **`--fix`** для oxlint/eslint — див. приклад workflow нижче). Без **prettier** і **@nitra/prettier-config**. У **`devDependencies`** має бути **`@nitra/eslint-config` мінімум `^3.5.0`** ним транзитивно йде **`@e18e/eslint-plugin`** для oxlint); пакет **`@e18e/eslint-plugin`** окремо не додавай. Пакети oxlint/eslint/jscpd не додавай без потреби монорепо.
8
8
 
9
9
  ```json title=".vscode/extensions.json"
10
10
  {
@@ -22,7 +22,7 @@ version: '1.11'
22
22
  "lint-js": "bunx oxlint --fix && bunx eslint --fix . && bunx jscpd ."
23
23
  },
24
24
  "devDependencies": {
25
- "@nitra/eslint-config": "^3.4.0"
25
+ "@nitra/eslint-config": "^3.5.0"
26
26
  },
27
27
  "engines": {
28
28
  "node": ">=24"
@@ -30,6 +30,17 @@ version: '1.11'
30
30
  }
31
31
  ```
32
32
 
33
+ У корені має бути **`.oxlintrc.json`** з підключенням **`@e18e/eslint-plugin`** через **`jsPlugins`** і правилом **`e18e/prefer-includes`** зі значенням **`error`**. Модуль **`@e18e/eslint-plugin`** не оголошуй окремо в **`package.json`** — він уже в залежностях **`@nitra/eslint-config`** (з **3.5.0**), oxlint резолвить його з **`node_modules`**.
34
+
35
+ ```json title=".oxlintrc.json (фрагмент)"
36
+ {
37
+ "jsPlugins": ["@e18e/eslint-plugin"],
38
+ "rules": {
39
+ "e18e/prefer-includes": "error"
40
+ }
41
+ }
42
+ ```
43
+
33
44
  У корені проєкту має бути `.jscpd.json`. Мінімум: увімкнути облік `.gitignore`, ненульовий код виходу при знаходженні клонів, консольний звіт. За потреби додай `ignore` (дзеркальні каталоги, шаблони) та `minLines`, щоб відсікти дрібні збіги:
34
45
 
35
46
  ```json title=".jscpd.json"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitra/cursor",
3
- "version": "1.8.95",
3
+ "version": "1.8.96",
4
4
  "description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
5
5
  "keywords": [
6
6
  "cli",
@@ -2,9 +2,10 @@
2
2
  * Перевіряє лінт JavaScript за правилом js-lint.mdc.
3
3
  *
4
4
  * Канонічний `lint-js`, flat ESLint з getConfig і ignore для auto-imports, рекомендації VSCode,
5
- * `.jscpd.json` (gitignore, exitCode, reporters, minLines), workflow `lint-js.yml` (checkout@v6,
6
- * setup-bun-deps, bunx без --fix), без prettier, `engines.node` >= 24. Дубль перевірки JS у `lint.yml`
7
- * заборонено.
5
+ * `.oxlintrc.json` з `jsPlugins` (`@e18e/eslint-plugin`) і правилом `e18e/prefer-includes: error`,
6
+ * `@nitra/eslint-config` у devDependencies мінімум **3.5.0** (транзитивний `@e18e/eslint-plugin` для oxlint), `.jscpd.json`
7
+ * (gitignore, exitCode, reporters, minLines), workflow `lint-js.yml` (checkout@v6, setup-bun-deps,
8
+ * bunx без --fix), без prettier, `engines.node` >= 24. Дубль перевірки JS у `lint.yml` — заборонено.
8
9
  */
9
10
  import { existsSync } from 'node:fs'
10
11
  import { readFile } from 'node:fs/promises'
@@ -36,6 +37,55 @@ export function isCanonicalLintJs(script) {
36
37
  return normalizeLintJsScript(script) === CANONICAL_LINT_JS
37
38
  }
38
39
 
40
+ /**
41
+ * Чи діапазон `@nitra/eslint-config` у `package.json` передбачає версію з транзитивним `@e18e/eslint-plugin` (>=3.5.0).
42
+ *
43
+ * @param {unknown} versionSpec значення `devDependencies['@nitra/eslint-config']`
44
+ * @returns {boolean} true для `workspace:*` або першої semver у рядку >= 3.5.0
45
+ */
46
+ export function nitraEslintConfigDeclaresE18eTransitive(versionSpec) {
47
+ const s = String(versionSpec).trim()
48
+ if (s.startsWith('workspace:')) {
49
+ return true
50
+ }
51
+ const m = s.match(/(\d+)\.(\d+)\.(\d+)/u)
52
+ if (!m) {
53
+ return false
54
+ }
55
+ const major = Number(m[1])
56
+ const minor = Number(m[2])
57
+ const patch = Number(m[3])
58
+ return major > 3 || (major === 3 && minor > 5) || (major === 3 && minor === 5 && patch >= 0)
59
+ }
60
+
61
+ /**
62
+ * Перевіряє обов’язкові поля `.oxlintrc.json` для плагіна e18e (js-lint.mdc).
63
+ *
64
+ * @param {unknown} cfg корінь JSON-конфігурації oxlint
65
+ * @returns {{ ok: boolean, failures: string[] }} `ok` і перелік повідомлень для `fail`
66
+ */
67
+ export function verifyOxlintRcE18e(cfg) {
68
+ const failures = []
69
+ if (!cfg || typeof cfg !== 'object' || Array.isArray(cfg)) {
70
+ return { ok: false, failures: ['.oxlintrc.json: корінь має бути об’єктом'] }
71
+ }
72
+ const o = /** @type {Record<string, unknown>} */ (cfg)
73
+ const jsPlugins = o.jsPlugins
74
+ if (!Array.isArray(jsPlugins) || !jsPlugins.includes('@e18e/eslint-plugin')) {
75
+ failures.push('.oxlintrc.json: jsPlugins має містити "@e18e/eslint-plugin"')
76
+ }
77
+ const rules = o.rules
78
+ if (!rules || typeof rules !== 'object' || Array.isArray(rules)) {
79
+ failures.push('.oxlintrc.json: поле rules має бути об’єктом')
80
+ } else {
81
+ const r = /** @type {Record<string, unknown>} */ (rules)
82
+ if (r['e18e/prefer-includes'] !== 'error') {
83
+ failures.push('.oxlintrc.json: у rules має бути "e18e/prefer-includes": "error"')
84
+ }
85
+ }
86
+ return { ok: failures.length === 0, failures }
87
+ }
88
+
39
89
  /**
40
90
  * Перевіряє відповідність проєкту правилам js-lint.mdc
41
91
  * @returns {Promise<number>} 0 — все OK, 1 — є проблеми
@@ -103,8 +153,16 @@ export async function check() {
103
153
  pass('package.json не містить @nitra/prettier-config')
104
154
  }
105
155
 
106
- if (pkg.devDependencies?.['@nitra/eslint-config']) {
156
+ const nitraEslint = pkg.devDependencies?.['@nitra/eslint-config']
157
+ if (nitraEslint) {
107
158
  pass('@nitra/eslint-config є в devDependencies')
159
+ if (nitraEslintConfigDeclaresE18eTransitive(nitraEslint)) {
160
+ pass('@nitra/eslint-config: мінімум 3.5.0 (транзитивний @e18e/eslint-plugin для oxlint jsPlugins, js-lint.mdc)')
161
+ } else {
162
+ fail(
163
+ '@nitra/eslint-config: онови до мінімум "^3.5.0" — з цієї версії постачається @e18e/eslint-plugin для .oxlintrc.json (js-lint.mdc)'
164
+ )
165
+ }
108
166
  } else {
109
167
  fail('@nitra/eslint-config відсутній в devDependencies — додай: bun add -d @nitra/eslint-config')
110
168
  }
@@ -122,6 +180,29 @@ export async function check() {
122
180
  }
123
181
  }
124
182
 
183
+ if (existsSync('.oxlintrc.json')) {
184
+ let oxCfg
185
+ try {
186
+ oxCfg = JSON.parse(await readFile('.oxlintrc.json', 'utf8'))
187
+ } catch {
188
+ fail('.oxlintrc.json не є валідним JSON')
189
+ oxCfg = null
190
+ }
191
+ if (oxCfg !== null) {
192
+ pass('.oxlintrc.json існує')
193
+ const oxV = verifyOxlintRcE18e(oxCfg)
194
+ if (oxV.ok) {
195
+ pass('.oxlintrc.json: jsPlugins з @e18e/eslint-plugin і e18e/prefer-includes: error')
196
+ } else {
197
+ for (const msg of oxV.failures) {
198
+ fail(msg)
199
+ }
200
+ }
201
+ }
202
+ } else {
203
+ fail('.oxlintrc.json не існує — додай конфіг oxlint (js-lint.mdc)')
204
+ }
205
+
125
206
  if (existsSync('.vscode/extensions.json')) {
126
207
  let ext
127
208
  try {