@nitra/cursor 12.14.0 → 12.15.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 +6 -0
- package/bin/docs/n-cursor.md +1 -4
- package/bin/n-cursor.js +1 -10
- package/package.json +1 -1
- package/scripts/lib/root-notice.mjs +2 -2
- package/scripts/lib/skill-meta.mjs +1 -1
- package/skills/start-check/SKILL.md +0 -74
- package/skills/start-check/js/check.mjs +0 -198
- package/skills/start-check/js/docs/check.md +0 -42
- package/skills/start-check/js/docs/index.md +0 -11
- package/skills/start-check/main.json +0 -1
package/CHANGELOG.md
CHANGED
package/bin/docs/n-cursor.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
Файл `npm/bin/n-cursor.js` — це виконуваний скрипт (shebang `#!/usr/bin/env node`), що слугує єдиною точкою входу CLI пакета `@nitra/cursor`. Скрипт виконує дві ролі:
|
|
6
6
|
|
|
7
7
|
1. **Синхронізатор пакетних артефактів у проєкті-споживачі** — без аргументів копіює `.mdc`-правила, скіли, slash-команди, генерує `AGENTS.md`, `CLAUDE.md`, синхронізує `.claude/settings.json`, `.cursor/hooks.json`, composite GitHub Action `setup-bun-deps`, `.pi/skills`, а також `.gitignore` для `.worktrees/`.
|
|
8
|
-
2. **Маршрутизатор підкоманд** — диспатчить `
|
|
8
|
+
2. **Маршрутизатор підкоманд** — диспатчить `rename-yaml-extensions`, `hook`, `lint`, `analyze-escalation`, `taze`, `release`, `skill`, `trace`, `adr-normalize-local`, `doc-aggregate` у відповідні внутрішні модулі пакета.
|
|
9
9
|
|
|
10
10
|
Скрипт — ES-модуль (`import` синтаксис). Виконує реальні файлові операції в `cwd()` і у каталогах пакету (`BUNDLED_PACKAGE_ROOT`). Усі шляхи відносно поточної робочої директорії проєкту-споживача.
|
|
11
11
|
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
- `npx @nitra/cursor lint` — data-driven оркестратор lint+конформності: `--full` (весь репо, включно з `full`-правилами), `--read-only` (CI, нуль мутацій); без прапорів — per-file дельта vs origin.
|
|
21
21
|
- `npx @nitra/cursor lint-ci` — те саме у CI-режимі.
|
|
22
22
|
- `npx @nitra/cursor coverage [--fix] [--changed]` — оркестратор покриття та мутаційного тестування.
|
|
23
|
-
- `npx @nitra/cursor change` — створення change-файлу.
|
|
24
23
|
- `npx @nitra/cursor release` — реліз-команда.
|
|
25
24
|
- `npx @nitra/cursor skill list|taze|cursor|claude …` — керування скілами (промпт на stdout, виклик Cursor/Claude CLI).
|
|
26
25
|
- `npx @nitra/cursor worktree …` — керування git-worktree.
|
|
@@ -462,7 +461,6 @@ try {
|
|
|
462
461
|
- `'lint'` → `runLint({ full, readOnly, rules })` (прапори `--full`, `--read-only`; позиційні аргументи — фільтр правил конформності).
|
|
463
462
|
- `'lint-ci'` → `runLint({ ci: true })`.
|
|
464
463
|
- `'coverage'` → динамічний import `../rules/test/coverage/coverage.mjs`, виклик `runCoverageCli({ fix: args.includes('--fix'), changed: args.includes('--changed') })`.
|
|
465
|
-
- `'change'` → динамічний import `../rules/release/change.mjs` → `runChangeCli(args)`.
|
|
466
464
|
- `'release'` → динамічний import `../rules/release/release.mjs` → `runReleaseCli(args)`.
|
|
467
465
|
- `'skill'` → `runSkillsCli(args)` (синхронний).
|
|
468
466
|
- `'worktree'` → `runWorktreeCli(args)`.
|
|
@@ -519,7 +517,6 @@ try {
|
|
|
519
517
|
### Динамічні (lazy) залежності
|
|
520
518
|
|
|
521
519
|
- `../rules/test/coverage/coverage.mjs` — `runCoverageCli`.
|
|
522
|
-
- `../rules/release/change.mjs` — `runChangeCli`.
|
|
523
520
|
- `../rules/release/release.mjs` — `runReleaseCli`.
|
|
524
521
|
- `../scripts/dispatcher/trace.mjs` — `runTraceCli`.
|
|
525
522
|
- `../skills/docgen/js/docgen-scan.mjs` — `runDocgenScanCli`, `runDocgenModulesCli`.
|
package/bin/n-cursor.js
CHANGED
|
@@ -1546,15 +1546,6 @@ try {
|
|
|
1546
1546
|
|
|
1547
1547
|
break
|
|
1548
1548
|
}
|
|
1549
|
-
case 'start-check': {
|
|
1550
|
-
// n-cursor start-check scan|run — детермінована частина smoke-перевірки для
|
|
1551
|
-
// скілу n-start-check: scan виявляє воркспейси зі start і їх тип, run запускає
|
|
1552
|
-
// один із grace-таймаутом і класифікує OK/FAIL. Агент лишається з діагностикою.
|
|
1553
|
-
const { runStartCheckCli } = await import('../skills/start-check/js/check.mjs')
|
|
1554
|
-
process.exitCode = await runStartCheckCli(args)
|
|
1555
|
-
|
|
1556
|
-
break
|
|
1557
|
-
}
|
|
1558
1549
|
case 'release': {
|
|
1559
1550
|
const { runReleaseCli } = await import('../rules/release/release.mjs')
|
|
1560
1551
|
process.exitCode = await runReleaseCli(args)
|
|
@@ -1584,7 +1575,7 @@ try {
|
|
|
1584
1575
|
default: {
|
|
1585
1576
|
console.error(`❌ Невідома команда: ${command}`)
|
|
1586
1577
|
console.error(
|
|
1587
|
-
` Очікується: (без аргументів) синхронізація правил, rename-yaml-extensions, hook, adr-normalize-local, lint (включно зі scope: lint ga|rego|k8s|docker|text), analyze-escalation, taze,
|
|
1578
|
+
` Очікується: (без аргументів) синхронізація правил, rename-yaml-extensions, hook, adr-normalize-local, lint (включно зі scope: lint ga|rego|k8s|docker|text), analyze-escalation, taze, release, skill, doc-aggregate`
|
|
1588
1579
|
)
|
|
1589
1580
|
process.exitCode = 1
|
|
1590
1581
|
}
|
package/package.json
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Worktree-скіли (`worktree: true`) свій root-assert уже мають у worktree-блоці
|
|
7
7
|
* (`worktree-notice.mjs`): корінь worktree = його toplevel. Цей модуль — для
|
|
8
|
-
* не-worktree-кейсу (напр. `n-
|
|
9
|
-
*
|
|
8
|
+
* не-worktree-кейсу (напр. `n-taze`, що мутує `package.json` безпосередньо
|
|
9
|
+
* й має стартувати з кореня монорепо).
|
|
10
10
|
*
|
|
11
11
|
* Блок — інструкція агенту, що читає `SKILL.md`; вставляється між стабільними
|
|
12
12
|
* маркерами, ре-синк ідемпотентний: наявний блок замінюється, при `false` —
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - `requireRoot` — boolean, опційне: чи скіл вимагає запуску з кореня репо.
|
|
8
8
|
* Worktree-скіли (`worktree:true`) вимагають кореня неявно (корінь worktree =
|
|
9
9
|
* його toplevel), тож для них поле зайве. Явний `requireRoot:true` — для
|
|
10
|
-
* in-place скілів, що мутують CWD без worktree-ізоляції (напр. `n-
|
|
10
|
+
* in-place скілів, що мутують CWD без worktree-ізоляції (напр. `n-taze`).
|
|
11
11
|
*
|
|
12
12
|
* Цим хелпером користуються `auto-skills.mjs` (автоактивація), `n-cursor.js`
|
|
13
13
|
* (sync + вшивання worktree/root-блоку) і check-концерн `npm-module/js/skill_meta.mjs`,
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: n-start-check
|
|
3
|
-
description: >-
|
|
4
|
-
Smoke-перевірка bun-монорепо: зайти в кожен воркспейс зі `start`-скриптом, прогнати
|
|
5
|
-
`start` і зафіксувати, чи проєкт взагалі запускається без негайного краху
|
|
6
|
-
version: '1.0'
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# n-start-check — чи запускається кожен воркспейс
|
|
10
|
-
|
|
11
|
-
## Мета
|
|
12
|
-
|
|
13
|
-
Прогнати `start`-скрипт у кожному воркспейсі bun-монорепо й зафіксувати, чи проєкт **взагалі стартує**. Це smoke-перевірка: ціль — спіймати негайний крах (синтаксична помилка, відсутній модуль, падіння на старті), а не протестувати поведінку.
|
|
14
|
-
|
|
15
|
-
## Передумови
|
|
16
|
-
|
|
17
|
-
- Bun-монорепо: кореневий `package.json` має поле `workspaces`.
|
|
18
|
-
- Залежності встановлені (`bun i`) — інакше `start` упаде на відсутньому модулі, а не на реальній проблемі.
|
|
19
|
-
- Запуск з кореня репозиторію (де лежить кореневий `package.json` / `bun.lock`).
|
|
20
|
-
|
|
21
|
-
## Workflow
|
|
22
|
-
|
|
23
|
-
### 1. Зібрати список воркспейсів
|
|
24
|
-
|
|
25
|
-
> **Не парси `package.json`/glob вручну.** Розгортання воркспейсів і класифікацію `start` несе CLI.
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
n-cursor start-check scan
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
Друкує JSON `[{ workspace, name, hasStart, startCmd, type }]` для root + усіх воркспейсів. `type` — `server` (dev-сервер/демон) чи `cli` (разова дія). Воркспейси з `hasStart:false` — `SKIP (немає start)` у звіті; решту прогоняй послідовно (крок 2).
|
|
32
|
-
|
|
33
|
-
### 2. Прогнати `start` кожного воркспейсу — по черзі
|
|
34
|
-
|
|
35
|
-
> **Не запускай `perl alarm` і не інтерпретуй exit-коди вручну.** CLI запускає процес із grace-таймаутом (крос-платформно через `spawnSync`), класифікує OK/FAIL за типом і парсить лог.
|
|
36
|
-
|
|
37
|
-
Для кожного воркспейсу з `hasStart:true` (**по одному, НЕ паралельно** — dev-сервери конфліктують за портами):
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
n-cursor start-check run <workspace> # напр. demo (--grace <ms>, дефолт 12000)
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Друкує JSON:
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
{ workspace, type, exitCode, timedOut, status, ready, firstError, logTail, sideEffects }
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
- `status: "OK"` — server дожив до кінця grace (`timedOut`) або встиг віддати рядок готовності; cli вийшов із кодом `0`.
|
|
50
|
-
- `status: "FAIL"` — крах/ненульовий код до grace. `firstError` + `logTail` — для діагностики.
|
|
51
|
-
- `sideEffects: { newFiles, changedTracked }` — read-only git-diff проти стану до запуску (для кроку 3).
|
|
52
|
-
|
|
53
|
-
Розрізняй **помилку коду** (синтаксис, відсутній імпорт, падіння на ініціалізації) і **середовищний збій** (немає `.env`, недоступна БД/порт зайнятий) — останній не означає, що проєкт зламаний.
|
|
54
|
-
|
|
55
|
-
### 3. Відкотити побічні ефекти прогону
|
|
56
|
-
|
|
57
|
-
CLI **не** мутує дерево сам (відкат — деструктивний, лишається явним). Якщо `run` повернув непорожній `sideEffects`, відкоти **лише те, що зʼявилося через прогін**, перш ніж запускати наступний воркспейс:
|
|
58
|
-
|
|
59
|
-
- `sideEffects.newFiles` — нові невідстежувані файли/директорії → видали (`rm`);
|
|
60
|
-
- `sideEffects.changedTracked` — відстежувані файли, що стали зміненими → `git checkout -- <path>`.
|
|
61
|
-
|
|
62
|
-
Усе, що було брудним **до** прогону, у `sideEffects` не потрапляє (CLI рахує лише різницю) — зміни користувача не чіпай. Gitignored-артефакти (кеші, `node_modules`) у git-diff не зʼявляються.
|
|
63
|
-
|
|
64
|
-
### 4. Звіт
|
|
65
|
-
|
|
66
|
-
Підсумкова таблиця: `воркспейс | статус | примітка`, з даних `scan` + `run`:
|
|
67
|
-
|
|
68
|
-
- `OK` — `status:"OK"` (живий dev-сервер або вихід `0`).
|
|
69
|
-
- `FAIL` — `status:"FAIL"`; додай `firstError` / `logTail`.
|
|
70
|
-
- `SKIP` — `hasStart:false`.
|
|
71
|
-
|
|
72
|
-
Якщо `run` повернув непорожній `sideEffects` — познач у примітці: проєкт стартує, але `start` не є чистим запуском (мутує репо). Якщо є хоч один `FAIL` — винеси його окремо з повною помилкою.
|
|
73
|
-
|
|
74
|
-
Скіл лише **діагностує** запуск. Виправлення коду — поза скоупом; якщо причина FAIL очевидна, познач її у звіті, але не правь, поки про це не попросять окремо.
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
/** @see ./docs/check.md */
|
|
2
|
-
import { spawnSync } from 'node:child_process'
|
|
3
|
-
import { existsSync } from 'node:fs'
|
|
4
|
-
import { readFile } from 'node:fs/promises'
|
|
5
|
-
import { join } from 'node:path'
|
|
6
|
-
|
|
7
|
-
import { getMonorepoPackageRootDirs } from '../../../scripts/lib/workspaces.mjs'
|
|
8
|
-
|
|
9
|
-
/** Маркери довгого процесу (dev-сервер/демон) у команді `start`. */
|
|
10
|
-
const SERVER_CMD_RE = /\b(vite|next|nuxt|nodemon|serve|astro|remix|webpack-dev-server|http-server)\b|\bdev\b|--watch/
|
|
11
|
-
/** Рядки готовності dev-сервера в логу (`\b` лише де треба — щоб «already» не матчив «ready»). */
|
|
12
|
-
const READY_RE = /\bready\b|\blistening\b|\bstarted\b|\bcompiled\b|server running|local:/i
|
|
13
|
-
/** Сигнатури помилок у логу. */
|
|
14
|
-
const ERROR_RE = /(error|exception|fatal|cannot find|module not found|unhandled|panic|traceback)/i
|
|
15
|
-
/** Скільки останніх рядків логу повертати. */
|
|
16
|
-
const LOG_TAIL_LINES = 15
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Класифікує `start`-команду: довгий процес (сервер) чи разова дія (CLI).
|
|
20
|
-
* @param {string} startCmd значення `scripts.start`
|
|
21
|
-
* @returns {'server'|'cli'} тип процесу
|
|
22
|
-
*/
|
|
23
|
-
export function classifyStartType(startCmd) {
|
|
24
|
-
return typeof startCmd === 'string' && SERVER_CMD_RE.test(startCmd) ? 'server' : 'cli'
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Зчитує `package.json` воркспейсу або повертає null.
|
|
29
|
-
* @param {string} dir абсолютний шлях до каталогу воркспейсу
|
|
30
|
-
* @returns {Promise<object|null>} розпарсений package.json або null
|
|
31
|
-
*/
|
|
32
|
-
async function readPkg(dir) {
|
|
33
|
-
const path = join(dir, 'package.json')
|
|
34
|
-
if (!existsSync(path)) return null
|
|
35
|
-
try {
|
|
36
|
-
return JSON.parse(await readFile(path, 'utf8'))
|
|
37
|
-
} catch {
|
|
38
|
-
return null
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Сканує монорепо: для кожного воркспейсу — чи є `start`, його команда і тип.
|
|
44
|
-
* @param {string} cwd корінь репозиторію
|
|
45
|
-
* @returns {Promise<Array<{workspace:string, name:string|null, hasStart:boolean, startCmd:string|null, type:('server'|'cli'|null)}>>} список воркспейсів
|
|
46
|
-
*/
|
|
47
|
-
export async function scanStartWorkspaces(cwd) {
|
|
48
|
-
const roots = await getMonorepoPackageRootDirs(cwd)
|
|
49
|
-
const out = []
|
|
50
|
-
for (const ws of roots) {
|
|
51
|
-
const pkg = await readPkg(join(cwd, ws))
|
|
52
|
-
const startCmd = pkg?.scripts?.start ?? null
|
|
53
|
-
const hasStart = typeof startCmd === 'string' && startCmd.length > 0
|
|
54
|
-
out.push({
|
|
55
|
-
workspace: ws,
|
|
56
|
-
name: pkg?.name ?? null,
|
|
57
|
-
hasStart,
|
|
58
|
-
startCmd: hasStart ? startCmd : null,
|
|
59
|
-
type: hasStart ? classifyStartType(startCmd) : null
|
|
60
|
-
})
|
|
61
|
-
}
|
|
62
|
-
return out
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Парсить лог процесу: готовність (сервер), перша помилка, хвіст.
|
|
67
|
-
* @param {string} log обʼєднаний stdout+stderr
|
|
68
|
-
* @returns {{ready:boolean, firstError:string|null, logTail:string}} витяг
|
|
69
|
-
*/
|
|
70
|
-
export function parseStartLog(log = '') {
|
|
71
|
-
const text = log
|
|
72
|
-
const lines = text.split('\n')
|
|
73
|
-
const firstError = lines.find(l => ERROR_RE.test(l))?.trim() ?? null
|
|
74
|
-
const logTail = lines
|
|
75
|
-
.filter(l => l.trim() !== '')
|
|
76
|
-
.slice(-LOG_TAIL_LINES)
|
|
77
|
-
.join('\n')
|
|
78
|
-
return { ready: READY_RE.test(text), firstError, logTail }
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Read-only знімок `git status --porcelain` як множина рядків.
|
|
83
|
-
* @param {string} cwd корінь репозиторію
|
|
84
|
-
* @returns {Set<string>} рядки porcelain (статус + шлях)
|
|
85
|
-
*/
|
|
86
|
-
function gitPorcelain(cwd) {
|
|
87
|
-
const res = spawnSync('git', ['status', '--porcelain'], { cwd, encoding: 'utf8' })
|
|
88
|
-
if (res.status !== 0 || typeof res.stdout !== 'string') return new Set()
|
|
89
|
-
return new Set(res.stdout.split('\n').filter(l => l.trim() !== ''))
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Обчислює побічні ефекти прогону як різницю git-станів до/після.
|
|
94
|
-
* @param {Set<string>} before знімок до
|
|
95
|
-
* @param {Set<string>} after знімок після
|
|
96
|
-
* @returns {{newFiles:string[], changedTracked:string[]}} нові untracked і ново-змінені tracked шляхи
|
|
97
|
-
*/
|
|
98
|
-
function diffSideEffects(before, after) {
|
|
99
|
-
const newFiles = []
|
|
100
|
-
const changedTracked = []
|
|
101
|
-
for (const line of after) {
|
|
102
|
-
if (before.has(line)) continue
|
|
103
|
-
const path = line.slice(3)
|
|
104
|
-
if (line.startsWith('??')) newFiles.push(path)
|
|
105
|
-
else changedTracked.push(path)
|
|
106
|
-
}
|
|
107
|
-
return { newFiles, changedTracked }
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Запускає `start` одного воркспейсу з grace-таймаутом і класифікує результат.
|
|
112
|
-
* @param {string} cwd корінь репозиторію
|
|
113
|
-
* @param {string} workspace відносний шлях воркспейсу
|
|
114
|
-
* @param {{graceMs?:number, type?:('server'|'cli'), spawnImpl?:typeof import('node:child_process').spawnSync}} [opts] grace-період, тип (інакше з package.json), інʼєкція spawn для тестів
|
|
115
|
-
* @returns {Promise<{workspace:string, type:string, exitCode:number|null, timedOut:boolean, status:('OK'|'FAIL'), ready:boolean, firstError:string|null, logTail:string, sideEffects:{newFiles:string[], changedTracked:string[]}}>} результат прогону
|
|
116
|
-
*/
|
|
117
|
-
export async function runWorkspaceStart(cwd, workspace, opts = {}) {
|
|
118
|
-
const { graceMs = 12_000, spawnImpl = spawnSync } = opts
|
|
119
|
-
const dir = join(cwd, workspace)
|
|
120
|
-
const pkg = await readPkg(dir)
|
|
121
|
-
const startCmd = pkg?.scripts?.start
|
|
122
|
-
if (typeof startCmd !== 'string' || startCmd.length === 0) {
|
|
123
|
-
throw new Error(`У воркспейсі ${workspace} немає scripts.start`)
|
|
124
|
-
}
|
|
125
|
-
const type = opts.type ?? classifyStartType(startCmd)
|
|
126
|
-
|
|
127
|
-
const before = gitPorcelain(cwd)
|
|
128
|
-
const res = spawnImpl('bun', ['run', 'start'], {
|
|
129
|
-
cwd: dir,
|
|
130
|
-
encoding: 'utf8',
|
|
131
|
-
timeout: graceMs,
|
|
132
|
-
killSignal: 'SIGTERM'
|
|
133
|
-
})
|
|
134
|
-
const timedOut = res.error?.code === 'ETIMEDOUT' || res.signal === 'SIGTERM'
|
|
135
|
-
const exitCode = typeof res.status === 'number' ? res.status : null
|
|
136
|
-
const { ready, firstError, logTail } = parseStartLog(`${res.stdout ?? ''}${res.stderr ?? ''}`)
|
|
137
|
-
|
|
138
|
-
// server: успіх = дожив до кінця grace (timedOut) або встиг віддати рядок готовності.
|
|
139
|
-
// cli: успіх = чистий вихід 0 у межах grace.
|
|
140
|
-
let status
|
|
141
|
-
if (type === 'server') status = timedOut || ready ? 'OK' : 'FAIL'
|
|
142
|
-
else status = exitCode === 0 ? 'OK' : 'FAIL'
|
|
143
|
-
|
|
144
|
-
return {
|
|
145
|
-
workspace,
|
|
146
|
-
type,
|
|
147
|
-
exitCode,
|
|
148
|
-
timedOut,
|
|
149
|
-
status,
|
|
150
|
-
ready,
|
|
151
|
-
firstError,
|
|
152
|
-
logTail,
|
|
153
|
-
sideEffects: diffSideEffects(before, gitPorcelain(cwd))
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const USAGE = 'Usage: n-cursor start-check <scan | run <workspace> [--grace <ms>]>'
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* CLI: `scan` друкує список воркспейсів зі `start`; `run <ws>` запускає один і
|
|
161
|
-
* друкує класифікований результат. Обидва — JSON у stdout.
|
|
162
|
-
* @param {string[]} args аргументи після `start-check`
|
|
163
|
-
* @param {string} [cwd] корінь репозиторію (інʼєкція для тестів)
|
|
164
|
-
* @returns {Promise<number>} exit code
|
|
165
|
-
*/
|
|
166
|
-
export async function runStartCheckCli(args, cwd = process.cwd()) {
|
|
167
|
-
const sub = args[0]
|
|
168
|
-
|
|
169
|
-
if (sub === 'scan') {
|
|
170
|
-
process.stdout.write(`${JSON.stringify(await scanStartWorkspaces(cwd))}\n`)
|
|
171
|
-
return 0
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (sub === 'run') {
|
|
175
|
-
const workspace = args[1] && !args[1].startsWith('--') ? args[1] : undefined
|
|
176
|
-
if (!workspace) {
|
|
177
|
-
console.error(USAGE)
|
|
178
|
-
return 1
|
|
179
|
-
}
|
|
180
|
-
const graceAt = args.indexOf('--grace')
|
|
181
|
-
const graceMs = graceAt === -1 ? undefined : Number(args[graceAt + 1])
|
|
182
|
-
if (graceAt !== -1 && (!Number.isFinite(graceMs) || graceMs <= 0)) {
|
|
183
|
-
console.error('✗ --grace очікує додатнє число (мс)')
|
|
184
|
-
return 1
|
|
185
|
-
}
|
|
186
|
-
try {
|
|
187
|
-
const result = await runWorkspaceStart(cwd, workspace, graceMs ? { graceMs } : {})
|
|
188
|
-
process.stdout.write(`${JSON.stringify(result)}\n`)
|
|
189
|
-
return 0
|
|
190
|
-
} catch (error) {
|
|
191
|
-
console.error(`✗ ${error.message}`)
|
|
192
|
-
return 1
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
console.error(USAGE)
|
|
197
|
-
return 1
|
|
198
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: JS Module
|
|
3
|
-
title: check.mjs
|
|
4
|
-
resource: npm/skills/start-check/js/check.mjs
|
|
5
|
-
docgen:
|
|
6
|
-
crc: 1f8fb2f0
|
|
7
|
-
score: 95
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
Файл надає інструменти для класифікації типів процесу, сканування конфігурації воркспейсів, парсингу логів та запуску скриптів.
|
|
11
|
-
|
|
12
|
-
## Поведінка
|
|
13
|
-
|
|
14
|
-
classifyStartType
|
|
15
|
-
Визначає тип процесу як сервер чи CLI на основі команди.
|
|
16
|
-
|
|
17
|
-
scanStartWorkspaces
|
|
18
|
-
Сканує монорепо для отримання інформації про наявність та конфігурацію `start` скриптів у воркспейсах.
|
|
19
|
-
|
|
20
|
-
parseStartLog
|
|
21
|
-
Парсить лог процесу для визначення готовності, першої помилки та останніх рядків.
|
|
22
|
-
|
|
23
|
-
runWorkspaceStart
|
|
24
|
-
Запускає `start` для одного воркспейсу з тайм-аутом і класифікує результат.
|
|
25
|
-
|
|
26
|
-
runStartCheckCli
|
|
27
|
-
Обробляє аргументи командного рядка для сканування або запуску тестування воркспейсів.
|
|
28
|
-
|
|
29
|
-
## Публічний API
|
|
30
|
-
|
|
31
|
-
- classifyStartType — визначає, чи команда `start` належить до довготривалого процесу (серверу) чи одноразової дії (CLI).
|
|
32
|
-
- scanStartWorkspaces — переглядає монорепо, витягуючи команду `start`, її команду та тип для кожного воркспейсу.
|
|
33
|
-
- parseStartLog — витягує з логу стадії: готовність (сервер), перша помилка або фінальний результат.
|
|
34
|
-
- runWorkspaceStart — ініціює запуск `start` для одного воркспейсу з обмеженням часу та класифікує отриманий результат.
|
|
35
|
-
- runStartCheckCli — CLI-команда: команда `scan` генерує список воркспейсів зі `start`; команда `run <ws>` запускає один воркспейс і виводить класифікований результат у stdout.
|
|
36
|
-
|
|
37
|
-
## Гарантії поведінки
|
|
38
|
-
|
|
39
|
-
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
40
|
-
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
|
41
|
-
- За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
|
|
42
|
-
- Не звертається до мережі.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{ "auto": "завжди", "worktree": false, "requireRoot": true }
|