@nitra/cursor 1.13.73 → 1.13.74

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/bin/n-cursor.js CHANGED
@@ -1310,7 +1310,7 @@ try {
1310
1310
  break
1311
1311
  }
1312
1312
  case 'skill': {
1313
- process.exitCode = await runSkillsCli(args)
1313
+ process.exitCode = runSkillsCli(args)
1314
1314
 
1315
1315
  break
1316
1316
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitra/cursor",
3
- "version": "1.13.73",
3
+ "version": "1.13.74",
4
4
  "description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
5
5
  "keywords": [
6
6
  "cli",
@@ -7,7 +7,8 @@
7
7
  #
8
8
  # Перевіряє: якщо в `dependencies` є `vue`, то потрібні канонічні Vue/Vite
9
9
  # залежності, `devDependencies.vite` має бути мажорної версії ≥ 8, а `esbuild`
10
- # у dependencies/devDependencies заборонений (міграція на rolldown).
10
+ # (міграція на rolldown), `vitest` (заміна на Bun Test Runner) і `jsdom`
11
+ # (заміна на happy-dom) у dependencies/devDependencies заборонені.
11
12
  #
12
13
  # AST-сканування коду (заборона явних value-імпортів `from 'vue'`, заборона
13
14
  # Node-нативних модулів у `.vue` SFC, перевірка `vite.config` на
@@ -65,6 +66,18 @@ deny contains msg if {
65
66
  msg := "Vue-пакет: esbuild заборонено — заміни на rolldown і прибери залежність (vue.mdc)"
66
67
  }
67
68
 
69
+ deny contains msg if {
70
+ uses_vue
71
+ "vitest" in all_dependency_names
72
+ msg := "Vue-пакет: vitest заборонено — використовуй Bun Test Runner (`bun test`) і прибери залежність (vue.mdc)"
73
+ }
74
+
75
+ deny contains msg if {
76
+ uses_vue
77
+ "jsdom" in all_dependency_names
78
+ msg := "Vue-пакет: jsdom заборонено — використовуй happy-dom і прибери залежність (vue.mdc)"
79
+ }
80
+
68
81
  # ── helpers ────────────────────────────────────────────────────────────────
69
82
 
70
83
  uses_vue if {
@@ -32,8 +32,8 @@ const USAGE_LINES = [
32
32
  ]
33
33
 
34
34
  /**
35
- * @param {string} name
36
- * @returns {boolean}
35
+ * @param {string} name ім'я бінарника
36
+ * @returns {boolean} чи знайдено бінарник у PATH
37
37
  */
38
38
  function isBinaryInPath(name) {
39
39
  const probe = spawnSync('command', ['-v', name], { shell: true, encoding: 'utf8' })
@@ -53,7 +53,7 @@ export function normalizeSkillId(name) {
53
53
 
54
54
  /**
55
55
  * @param {string} skillsRoot абсолютний шлях до `skills/` пакета
56
- * @returns {string[]}
56
+ * @returns {string[]} відсортовані id скілів, що мають `SKILL.md`
57
57
  */
58
58
  export function listSkillIds(skillsRoot) {
59
59
  if (!existsSync(skillsRoot)) {
@@ -64,32 +64,32 @@ export function listSkillIds(skillsRoot) {
64
64
  .filter(entry => entry.isDirectory())
65
65
  .map(entry => entry.name)
66
66
  .filter(name => existsSync(join(skillsRoot, name, 'SKILL.md')))
67
- .sort((a, b) => a.localeCompare(b))
67
+ .toSorted((a, b) => a.localeCompare(b))
68
68
  }
69
69
 
70
70
  /**
71
- * @param {string} skillsRoot
71
+ * @param {string} skillsRoot абсолютний шлях до `skills/` пакета
72
72
  * @param {string} skillId нормалізований id (без префікса n-)
73
- * @returns {string}
73
+ * @returns {string} шлях до `SKILL.md` скілу
74
74
  */
75
75
  function getSkillMdPath(skillsRoot, skillId) {
76
76
  return join(skillsRoot, skillId, 'SKILL.md')
77
77
  }
78
78
 
79
79
  /**
80
- * @param {string} path
81
- * @returns {string | null}
80
+ * @param {string} path шлях до файлу
81
+ * @returns {string | null} вміст файлу або `null`, якщо файлу немає
82
82
  */
83
83
  function readIfExists(path) {
84
84
  return existsSync(path) ? readFileSync(path, 'utf8') : null
85
85
  }
86
86
 
87
87
  /**
88
- * @param {string} skillsRoot
89
- * @param {string} rawSkillName
90
- * @param {string} task
91
- * @param {string} [projectDir]
92
- * @returns {string}
88
+ * @param {string} skillsRoot абсолютний шлях до `skills/` пакета
89
+ * @param {string} rawSkillName ім'я скілу з CLI (можливо з префіксом n-)
90
+ * @param {string} task текст завдання для скілу
91
+ * @param {string} [projectDir] корінь цільового проєкту (типово — CWD)
92
+ * @returns {string} промпт: інструкція скілу + контекст поточного проєкту
93
93
  */
94
94
  export function buildSkillPrompt(skillsRoot, rawSkillName, task, projectDir = cwd()) {
95
95
  const skillId = normalizeSkillId(rawSkillName)
@@ -124,10 +124,10 @@ export function buildSkillPrompt(skillsRoot, rawSkillName, task, projectDir = cw
124
124
  }
125
125
 
126
126
  /**
127
- * @param {'claude' | 'cursor'} kind
128
- * @param {string} prompt
129
- * @param {string} projectDir
130
- * @returns {number}
127
+ * @param {'claude' | 'cursor'} kind який LLM CLI запускати
128
+ * @param {string} prompt промпт для передачі у stdin
129
+ * @param {string} projectDir робочий каталог дочірнього процесу
130
+ * @returns {number} exit code дочірнього процесу
131
131
  */
132
132
  function runLlmCli(kind, prompt, projectDir) {
133
133
  if (kind === 'claude') {
@@ -159,8 +159,8 @@ function runLlmCli(kind, prompt, projectDir) {
159
159
 
160
160
  /**
161
161
  * Корінь пакета `@nitra/cursor` (каталог з `skills/`, `rules/`, …).
162
- * @param {string} [fromModuleUrl] для тестів — `import.meta.url` викликача
163
- * @returns {string}
162
+ * @param {string} [fromModuleUrl] для тестів — `import.meta.url`, відносно якого шукати корінь
163
+ * @returns {string} абсолютний шлях до кореня пакета
164
164
  */
165
165
  export function resolveBundledPackageRoot(fromModuleUrl = import.meta.url) {
166
166
  return join(dirname(fileURLToPath(fromModuleUrl)), '..')
@@ -168,10 +168,10 @@ export function resolveBundledPackageRoot(fromModuleUrl = import.meta.url) {
168
168
 
169
169
  /**
170
170
  * @param {string[]} argv аргументи після `skill` у `n-cursor`
171
- * @param {{ packageRoot?: string, projectDir?: string, log?: (line: string) => void, logError?: (line: string) => void }} [options]
172
- * @returns {Promise<number>} exit code
171
+ * @param {{ packageRoot?: string, projectDir?: string, log?: (line: string) => void, logError?: (line: string) => void }} [options] перевизначення кореня пакета, каталогу проєкту та функцій виводу (для тестів)
172
+ * @returns {number} exit code
173
173
  */
174
- export async function runSkillsCli(argv, options = {}) {
174
+ export function runSkillsCli(argv, options = {}) {
175
175
  const log = options.log ?? (line => console.log(line))
176
176
  const logError = options.logError ?? (line => console.error(line))
177
177
  const packageRoot = options.packageRoot ?? resolveBundledPackageRoot()
@@ -12,12 +12,7 @@ const TRAILING_SLASH_RE = /\/$/
12
12
  const LEADING_DOTSLASH_RE = /^\.\//
13
13
 
14
14
  /** Glob-ігнор для workspace-патернів із `*` (узгоджено з `package-manifest.mjs`). */
15
- export const WORKSPACE_GLOB_IGNORE = Object.freeze([
16
- '**/node_modules/**',
17
- '**/.git/**',
18
- '**/.venv/**',
19
- '**/venv/**'
20
- ])
15
+ export const WORKSPACE_GLOB_IGNORE = Object.freeze(['**/node_modules/**', '**/.git/**', '**/.venv/**', '**/venv/**'])
21
16
 
22
17
  /**
23
18
  * Чи слід виключити каталог зі списку workspace-коренів (не стосується `.`).
@@ -27,13 +22,8 @@ export const WORKSPACE_GLOB_IGNORE = Object.freeze([
27
22
  export function isIgnoredWorkspaceRoot(ws) {
28
23
  if (ws === '.') return false
29
24
  const p = ws.replaceAll('\\', '/').replace(LEADING_DOTSLASH_RE, '')
30
- const segments = p.split('/')
31
- return (
32
- segments.includes('node_modules') ||
33
- segments.includes('.git') ||
34
- segments.includes('.venv') ||
35
- segments.includes('venv')
36
- )
25
+ const segments = new Set(p.split('/'))
26
+ return segments.has('node_modules') || segments.has('.git') || segments.has('.venv') || segments.has('venv')
37
27
  }
38
28
 
39
29
  /**