@nitra/cursor 12.11.2 → 12.12.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 +13 -0
- package/bin/n-cursor.js +5 -37
- package/package.json +1 -1
- package/rules/bun/docs/index.md +2 -2
- package/rules/bun/docs/main.md +8 -9
- package/rules/bun/js/docs/index.md +3 -2
- package/rules/bun/main.json +1 -1
- package/rules/bun/main.mdc +3 -1
- package/rules/bun/main.mjs +63 -3
- package/rules/changelog/js/docs/index.md +3 -2
- package/rules/ci4/main.mdc +1 -0
- package/rules/ci4/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/ga/main.mdc +9 -1
- package/rules/ga/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/graphql/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/js/js/dep-policy.mdc +19 -0
- package/rules/js/js/dep-policy.mjs +14 -6
- package/rules/js/js/docs/index.md +5 -5
- package/rules/js/main.mdc +4 -0
- package/rules/js/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/js-run/js/docs/index.md +3 -2
- package/rules/js-run/main.mdc +3 -0
- package/rules/nginx-default-tpl/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/npm-module/main.mdc +4 -0
- package/rules/python/docs/index.md +2 -2
- package/rules/python/docs/main.md +13 -10
- package/rules/python/main.mjs +43 -0
- package/rules/rego/main.mdc +2 -0
- package/rules/rego/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/rust/docs/index.md +2 -2
- package/rules/rust/docs/main.md +10 -7
- package/rules/rust/main.json +1 -1
- package/rules/rust/main.mjs +23 -1
- package/rules/rust/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/security/main.mdc +2 -0
- package/rules/style/js/docs/index.md +3 -2
- package/rules/style/main.mdc +5 -1
- package/rules/style/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/tauri/policy/vscode_extensions/docs/index.md +11 -0
- package/rules/test/main.mdc +2 -1
- package/rules/text/main.mdc +9 -0
- package/rules/text/policy/vscode_extensions/docs/index.md +11 -0
- package/scripts/docs/index.md +14 -13
- package/scripts/docs/update-blue-oak.md +28 -0
- package/scripts/lib/blue-oak.mjs +45 -0
- package/scripts/lib/docs/blue-oak.md +29 -0
- package/scripts/lib/docs/index.md +35 -35
- package/scripts/lib/docs/run-rule.md +8 -6
- package/scripts/lib/fix/docs/index.md +12 -10
- package/scripts/lib/fix/docs/t0.md +7 -7
- package/scripts/lib/fix/t0.mjs +1 -2
- package/scripts/lib/run-rule.mjs +0 -11
- package/scripts/update-blue-oak.mjs +51 -0
- package/skills/doc-aggregate/SKILL.md +8 -18
- package/skills/doc-aggregate/js/docs/index.md +0 -1
- package/scripts/lib/check-mdc-template-refs.mjs +0 -57
- package/scripts/lib/docs/check-mdc-template-refs.md +0 -22
- package/skills/doc-aggregate/js/docgen-scan.mjs +0 -195
- package/skills/doc-aggregate/js/docs/docgen-scan.md +0 -76
|
@@ -37,29 +37,19 @@ npx @nitra/cursor lint-doc-files --git
|
|
|
37
37
|
|
|
38
38
|
## Крок 1: Tier 2 — module-summary
|
|
39
39
|
|
|
40
|
-
Зібрати список
|
|
40
|
+
Зібрати список воркспейсів з кореневого `package.json`:
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
|
|
43
|
+
node -e "const p=JSON.parse(require('fs').readFileSync('package.json','utf8')); console.log(JSON.stringify(p.workspaces))"
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
{
|
|
51
|
-
"moduleRoot": "/abs/npm/rules/adr",
|
|
52
|
-
"relRoot": "npm/rules/adr",
|
|
53
|
-
"slug": "npm-rules-adr",
|
|
54
|
-
"docPath": "/abs/npm/rules/adr/docs/ARCHITECTURE.md",
|
|
55
|
-
"members": ["npm/rules/adr/index.mjs"],
|
|
56
|
-
"exists": false
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
```
|
|
46
|
+
Для кожного воркспейсу `<ws>`:
|
|
47
|
+
- `relRoot` = `<ws>` (напр. `npm`, `demo`)
|
|
48
|
+
- `docPath` = `<ws>/docs/ARCHITECTURE.md`
|
|
49
|
+
- `members` — кодові файли (`.mjs .ts .vue .py`, крім тестів) у `<ws>/`
|
|
60
50
|
|
|
61
|
-
module-summary **завжди
|
|
62
|
-
|
|
51
|
+
module-summary **завжди регенерується**. Розбий воркспейси на батчі по 5 і диспатч субагентів.
|
|
52
|
+
Промпт кожного (підстав `relRoot`, `docPath`, `members`):
|
|
63
53
|
|
|
64
54
|
```
|
|
65
55
|
Напиши module-summary для одного логічного модуля.
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns list of template/ files that are NOT referenced in <id>.mdc as
|
|
3
|
-
* markdown link targets. Paths returned are relative to ruleDir.
|
|
4
|
-
*/
|
|
5
|
-
import { existsSync } from 'node:fs'
|
|
6
|
-
import { readdir, readFile, stat } from 'node:fs/promises'
|
|
7
|
-
import { join, relative } from 'node:path'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @param {string} ruleDir абсолютний шлях до каталогу правила
|
|
11
|
-
* @returns {Promise<string[]>} абсолютні шляхи всіх файлів у template/
|
|
12
|
-
*/
|
|
13
|
-
async function walkTemplateDirs(ruleDir) {
|
|
14
|
-
const out = []
|
|
15
|
-
for (const kind of ['fix', 'policy']) {
|
|
16
|
-
const kindDir = join(ruleDir, kind)
|
|
17
|
-
if (!existsSync(kindDir)) continue
|
|
18
|
-
for (const concern of await readdir(kindDir)) {
|
|
19
|
-
const tpl = join(kindDir, concern, 'template')
|
|
20
|
-
if (!existsSync(tpl)) continue
|
|
21
|
-
const tplStat = await stat(tpl)
|
|
22
|
-
if (!tplStat.isDirectory()) continue
|
|
23
|
-
out.push(...(await collectFiles(tpl)))
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return out.map(p => relative(ruleDir, p))
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param {string} dir каталог для обходу
|
|
31
|
-
* @returns {Promise<string[]>} абсолютні шляхи знайдених файлів
|
|
32
|
-
*/
|
|
33
|
-
async function collectFiles(dir) {
|
|
34
|
-
const out = []
|
|
35
|
-
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
36
|
-
const full = join(dir, entry.name)
|
|
37
|
-
if (entry.isDirectory()) out.push(...(await collectFiles(full)))
|
|
38
|
-
else out.push(full)
|
|
39
|
-
}
|
|
40
|
-
return out
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* @param {string} ruleDir абсолютний шлях до npm/rules/<id>/
|
|
45
|
-
* @param {string} ruleId basename правила (напр. "security")
|
|
46
|
-
* @returns {Promise<string[]>} відносні шляхи template-файлів без посилань у .mdc
|
|
47
|
-
*/
|
|
48
|
-
export async function findMissingMdcRefs(ruleDir) {
|
|
49
|
-
const mdcPath = join(ruleDir, 'main.mdc')
|
|
50
|
-
if (!existsSync(mdcPath)) return []
|
|
51
|
-
const mdc = await readFile(mdcPath, 'utf8')
|
|
52
|
-
const allFiles = await walkTemplateDirs(ruleDir)
|
|
53
|
-
return allFiles.filter(rel => {
|
|
54
|
-
// Match markdown link to ./<rel> or (<rel>) anywhere in the .mdc
|
|
55
|
-
return !mdc.includes(`./${rel}`) && !mdc.includes(`(${rel})`)
|
|
56
|
-
})
|
|
57
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: JS Module
|
|
3
|
-
title: check-mdc-template-refs.mjs
|
|
4
|
-
resource: npm/scripts/lib/check-mdc-template-refs.mjs
|
|
5
|
-
docgen:
|
|
6
|
-
crc: c116210e
|
|
7
|
-
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
|
-
score: 100
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
Визначає список файлів шаблонів, що знаходяться у каталогах `fix` та `policy`, які не є цільовими посиланнями у файлі `<id>.mdc` як markdown link targets. Це дозволяє ідентифікувати ресурси шаблонів, які не були згадані в контексті правила.
|
|
12
|
-
|
|
13
|
-
## Поведінка
|
|
14
|
-
|
|
15
|
-
1. Збирає абсолютні шляхи всіх файлів, що знаходяться у каталогах `template` всередині підкаталогів `fix` та `policy` у вказаному каталозі правила.
|
|
16
|
-
2. Зчитує вміст файлу `main.mdc` у каталозі правила.
|
|
17
|
-
3. Фільтрує зібрані шляхи, залишаючи лише ті, які не з'являються у вмісті `main.mdc` у вигляді посилання Markdown (`./<шлях>` або ``).
|
|
18
|
-
4. Повертає відносні шляхи цих незгаданих шаблонних файлів відносно каталогу правила.
|
|
19
|
-
|
|
20
|
-
## Гарантії поведінки
|
|
21
|
-
|
|
22
|
-
- Read-only: не виконує операцій запису (ФС/БД).
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
/** @see ./docs/docgen-scan.md */
|
|
2
|
-
import { join, relative, dirname, extname, sep, isAbsolute, resolve } from 'node:path'
|
|
3
|
-
import { existsSync, readdirSync, statSync } from 'node:fs'
|
|
4
|
-
|
|
5
|
-
import { isRunAsCli } from '../../../scripts/cli-entry.mjs'
|
|
6
|
-
import { isDocgenIgnored } from './docgen-ignore.mjs'
|
|
7
|
-
|
|
8
|
-
/** Кодові розширення, для яких генеруємо документацію. */
|
|
9
|
-
const SOURCE_EXTENSIONS = new Set(['.js', '.mjs', '.ts', '.vue', '.py'])
|
|
10
|
-
|
|
11
|
-
/** `*.test.*`, `*.spec.*` — тести, документувати не треба. */
|
|
12
|
-
const TEST_FILE_RE = /\.(?:test|spec)\.[^.]+$/u
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Чи корінь має system-wide docs layout (зарезервований під repo docs/adr тощо).
|
|
16
|
-
* @param {string} root абсолютний корінь обходу
|
|
17
|
-
* @returns {boolean} true — корінь system-wide docs
|
|
18
|
-
*/
|
|
19
|
-
function isSystemWideDocsRoot(root) {
|
|
20
|
-
return existsSync(join(root, 'docs', 'adr')) || existsSync(join(root, 'docs', 'explanation'))
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Чи є файл кодовим джерелом для документування.
|
|
25
|
-
* @param {string} fileName базове ім'я файлу
|
|
26
|
-
* @returns {boolean} true — документуємо
|
|
27
|
-
*/
|
|
28
|
-
export function isSourceFile(fileName) {
|
|
29
|
-
if (fileName.endsWith('.d.ts')) return false
|
|
30
|
-
if (TEST_FILE_RE.test(fileName)) return false
|
|
31
|
-
return SOURCE_EXTENSIONS.has(extname(fileName))
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Рекурсивно збирає кодові файли проєкту (posix-шляхи від кореня).
|
|
36
|
-
* @param {string} root абсолютний корінь обходу
|
|
37
|
-
* @returns {string[]} sourcePath-и
|
|
38
|
-
*/
|
|
39
|
-
export function scanSourceFiles(root) {
|
|
40
|
-
const results = []
|
|
41
|
-
|
|
42
|
-
/** @param {string} dir поточний каталог обходу */
|
|
43
|
-
function walk(dir) {
|
|
44
|
-
let entries
|
|
45
|
-
try {
|
|
46
|
-
entries = readdirSync(dir, { withFileTypes: true })
|
|
47
|
-
} catch {
|
|
48
|
-
return
|
|
49
|
-
}
|
|
50
|
-
for (const entry of entries) {
|
|
51
|
-
const fullPath = join(dir, entry.name)
|
|
52
|
-
const relPath = relative(root, fullPath)
|
|
53
|
-
if (entry.isDirectory()) {
|
|
54
|
-
if (isDocgenIgnored(relPath, 'dir')) continue
|
|
55
|
-
walk(fullPath)
|
|
56
|
-
} else if (entry.isFile() && isSourceFile(entry.name)) {
|
|
57
|
-
if (isSystemWideDocsRoot(root) && dirname(relPath) === '.') continue
|
|
58
|
-
const sourcePath = relPath.split(sep).join('/')
|
|
59
|
-
if (isDocgenIgnored(sourcePath)) continue
|
|
60
|
-
results.push(sourcePath)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
walk(root)
|
|
66
|
-
return results
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Стабільний slug модуля з його відносного шляху (для лейблів/логів).
|
|
71
|
-
* @param {string} root абсолютний корінь обходу
|
|
72
|
-
* @param {string} moduleRoot абсолютний корінь модуля
|
|
73
|
-
* @returns {string} slug: `npm/rules/adr` → `npm-rules-adr`, корінь → `root`
|
|
74
|
-
*/
|
|
75
|
-
export function slugForModule(root, moduleRoot) {
|
|
76
|
-
const rel = relative(root, moduleRoot)
|
|
77
|
-
if (rel === '') return 'root'
|
|
78
|
-
return rel
|
|
79
|
-
.split(sep)
|
|
80
|
-
.join('-')
|
|
81
|
-
.replaceAll(/[^\w-]+/gu, '-')
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Знаходить корені модулів — теки з `package.json` (корінь завжди модуль).
|
|
86
|
-
* @param {string} root абсолютний корінь обходу
|
|
87
|
-
* @returns {string[]} абсолютні шляхи коренів модулів
|
|
88
|
-
*/
|
|
89
|
-
export function findModuleRoots(root) {
|
|
90
|
-
const roots = [root]
|
|
91
|
-
|
|
92
|
-
/** @param {string} dir поточний каталог обходу */
|
|
93
|
-
function walk(dir) {
|
|
94
|
-
let entries
|
|
95
|
-
try {
|
|
96
|
-
entries = readdirSync(dir, { withFileTypes: true })
|
|
97
|
-
} catch {
|
|
98
|
-
return
|
|
99
|
-
}
|
|
100
|
-
for (const entry of entries) {
|
|
101
|
-
const fullPath = join(dir, entry.name)
|
|
102
|
-
const relPath = relative(root, fullPath)
|
|
103
|
-
if (entry.isDirectory()) {
|
|
104
|
-
if (isDocgenIgnored(relPath, 'dir')) continue
|
|
105
|
-
walk(fullPath)
|
|
106
|
-
} else if (entry.isFile() && entry.name === 'package.json' && dir !== root) {
|
|
107
|
-
roots.push(dir)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
walk(root)
|
|
113
|
-
return roots
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Найближчий модуль-предок для файлу (найдовший збіг шляху).
|
|
118
|
-
* @param {string} filePath абсолютний шлях до файлу
|
|
119
|
-
* @param {string[]} moduleRoots абсолютні корені модулів
|
|
120
|
-
* @returns {string|null} абсолютний корінь модуля або null
|
|
121
|
-
*/
|
|
122
|
-
export function nearestModuleRoot(filePath, moduleRoots) {
|
|
123
|
-
let best = null
|
|
124
|
-
for (const moduleRoot of moduleRoots) {
|
|
125
|
-
const rel = relative(moduleRoot, filePath)
|
|
126
|
-
if (rel.startsWith('..') || isAbsolute(rel)) continue
|
|
127
|
-
if (best === null || moduleRoot.length > best.length) best = moduleRoot
|
|
128
|
-
}
|
|
129
|
-
return best
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Лістить логічні модулі проєкту з членами-файлами і docPath module-summary.
|
|
134
|
-
* Модулі без кодових файлів пропускаються.
|
|
135
|
-
* @param {string} root абсолютний корінь обходу
|
|
136
|
-
* @returns {Array<{moduleRoot:string, relRoot:string, slug:string, docPath:string, members:string[], exists:boolean}>} модулі (members — sourcePath-и від root)
|
|
137
|
-
*/
|
|
138
|
-
export function scanForModules(root) {
|
|
139
|
-
const files = scanSourceFiles(root)
|
|
140
|
-
const moduleRoots = findModuleRoots(root)
|
|
141
|
-
const byRoot = new Map()
|
|
142
|
-
for (const sourcePath of files) {
|
|
143
|
-
const moduleRoot = nearestModuleRoot(join(root, sourcePath), moduleRoots)
|
|
144
|
-
if (moduleRoot === null) continue
|
|
145
|
-
if (!byRoot.has(moduleRoot)) byRoot.set(moduleRoot, [])
|
|
146
|
-
byRoot.get(moduleRoot).push(sourcePath)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const results = []
|
|
150
|
-
for (const moduleRoot of moduleRoots) {
|
|
151
|
-
const members = byRoot.get(moduleRoot)
|
|
152
|
-
if (!members || members.length === 0) continue
|
|
153
|
-
const docPath = join(moduleRoot, 'docs', 'ARCHITECTURE.md')
|
|
154
|
-
results.push({
|
|
155
|
-
moduleRoot,
|
|
156
|
-
relRoot: relative(root, moduleRoot) || '.',
|
|
157
|
-
slug: slugForModule(root, moduleRoot),
|
|
158
|
-
docPath,
|
|
159
|
-
members: members.toSorted(),
|
|
160
|
-
exists: existsSync(docPath)
|
|
161
|
-
})
|
|
162
|
-
}
|
|
163
|
-
return results
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Парсить `--root <dir>`; default — cwd.
|
|
168
|
-
* @param {string[]} argv аргументи після підкоманди
|
|
169
|
-
* @returns {string} абсолютний корінь
|
|
170
|
-
*/
|
|
171
|
-
export function resolveRoot(argv) {
|
|
172
|
-
const i = argv.indexOf('--root')
|
|
173
|
-
return i !== -1 && argv[i + 1] ? resolve(argv[i + 1]) : process.cwd()
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* `doc-aggregate modules` — сканує модулі і друкує JSON-масив у stdout.
|
|
178
|
-
* @param {string[]} argv аргументи після назви субкоманди
|
|
179
|
-
* @returns {number} exit-код: 0 — успіх, 1 — корінь не існує
|
|
180
|
-
*/
|
|
181
|
-
export function runDocAggregateModulesCli(argv) {
|
|
182
|
-
const root = resolveRoot(argv)
|
|
183
|
-
if (!existsSync(root) || !statSync(root).isDirectory()) {
|
|
184
|
-
console.error(`doc-aggregate modules: корінь не існує або не є директорією: ${root}`)
|
|
185
|
-
return 1
|
|
186
|
-
}
|
|
187
|
-
console.log(JSON.stringify(scanForModules(root), null, 2))
|
|
188
|
-
return 0
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (isRunAsCli(import.meta.url)) {
|
|
192
|
-
// Прямий запуск: `node skills/doc-aggregate/js/docgen-scan.mjs modules --root <dir>`
|
|
193
|
-
const [sub, ...rest] = process.argv.slice(2)
|
|
194
|
-
process.exitCode = runDocAggregateModulesCli(sub === 'modules' ? rest : process.argv.slice(2))
|
|
195
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: JS Module
|
|
3
|
-
title: docgen-scan.mjs
|
|
4
|
-
resource: npm/skills/doc-aggregate/js/docgen-scan.mjs
|
|
5
|
-
docgen:
|
|
6
|
-
crc: 193dd362
|
|
7
|
-
score: 100
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
isSourceFile
|
|
11
|
-
Перевіряє, чи є файл коду, який слугує джерелом для документування.
|
|
12
|
-
|
|
13
|
-
scanSourceFiles
|
|
14
|
-
Рекурсивно збирає кодові файли проєкту за позикс-шляхами від кореня.
|
|
15
|
-
|
|
16
|
-
slugForModule
|
|
17
|
-
Генерує стабільний slug модуля на основі його відносного шляху.
|
|
18
|
-
|
|
19
|
-
findModuleRoots
|
|
20
|
-
Знаходить абсолютні шляхи коренів модулів, використовуючи дані з package.json.
|
|
21
|
-
|
|
22
|
-
nearestModuleRoot
|
|
23
|
-
Визначає найближчий модуль-предок для заданого файлу серед усіх доступних коренів модулів.
|
|
24
|
-
|
|
25
|
-
scanForModules
|
|
26
|
-
Лістить логічні модулі, збираючи члени-файли та інформацію про наявність документації.
|
|
27
|
-
|
|
28
|
-
resolveRoot
|
|
29
|
-
Парсить аргументи для визначення абсолютної кореневої директорії.
|
|
30
|
-
|
|
31
|
-
runDocAggregateModulesCli
|
|
32
|
-
Сканує модулі та виводить масив JSON у stdout.
|
|
33
|
-
|
|
34
|
-
## Поведінка
|
|
35
|
-
|
|
36
|
-
isSourceFile
|
|
37
|
-
Перевіряє, чи є файл кодовим джерелом для документування
|
|
38
|
-
|
|
39
|
-
scanSourceFiles
|
|
40
|
-
Рекурсивно збирає кодові файли проєкту по позикс-шляхах від кореня
|
|
41
|
-
|
|
42
|
-
slugForModule
|
|
43
|
-
Генерує стабільний slug модуля з його відносним шляхом
|
|
44
|
-
|
|
45
|
-
findModuleRoots
|
|
46
|
-
Знаходить абсолютні шляхи коренів модулів з файлами package.json
|
|
47
|
-
|
|
48
|
-
nearestModuleRoot
|
|
49
|
-
Знаходить найближчий модуль-предок для файлу серед наявних коренів модулів
|
|
50
|
-
|
|
51
|
-
scanForModules
|
|
52
|
-
Лістить логічні модулі, збираючи члени-файли та інформацію про наявність документації
|
|
53
|
-
|
|
54
|
-
resolveRoot
|
|
55
|
-
Парсить аргументи для визначення абсолютного кореня
|
|
56
|
-
|
|
57
|
-
runDocAggregateModulesCli
|
|
58
|
-
Сканує модулі та виводить JSON-масив у stdout
|
|
59
|
-
|
|
60
|
-
## Публічний API
|
|
61
|
-
|
|
62
|
-
- isSourceFile — визначає, чи є файл коду для документування.
|
|
63
|
-
- scanSourceFiles — рекурсивно збирає файли коду проєкту (від кореня за POSIX-шляхом).
|
|
64
|
-
- slugForModule — генерує стабільний slug модуля з його відносним шляхом (для лейблів/логів).
|
|
65
|
-
- findModuleRoots — знаходить кореневі директорії модулів у `package.json` (корінь — це модуль).
|
|
66
|
-
- nearestModuleRoot — визначає найближчий модуль-предок для файлу (найдовший збіг шляху).
|
|
67
|
-
- scanForModules — лістить логічні модулі проєкту з членами-файлами та `docPath module-summary`. Пропускає модулі без кодових файлів.
|
|
68
|
-
- resolveRoot — парсить аргумент `--root <dir>`; за замовчуванням використовує поточну директорію.
|
|
69
|
-
- runDocAggregateModulesCli — виконує команду `doc-aggregate modules`, скануючи модулі та виводячи JSON-масив у stdout.
|
|
70
|
-
|
|
71
|
-
## Гарантії поведінки
|
|
72
|
-
|
|
73
|
-
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
74
|
-
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
|
75
|
-
- За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
|
|
76
|
-
- Не звертається до мережі.
|