@noyrax/documentation-system-plugin 1.0.4-beta.11 → 1.0.4-beta.13
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/package.json +1 -1
- package/scripts/verify-adrs.js +111 -20
- package/scripts/verify-architecture.js +50 -0
- package/scripts/verify-imports.js +81 -7
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@noyrax/documentation-system-plugin",
|
|
3
3
|
"displayName": "Noyrax",
|
|
4
4
|
"description": "Documentation that never drifts. Automatic documentation generation with validation and drift detection. Generates 5-dimensional documentation structure (modules, symbols, dependencies, ADRs, changes) for codebases.",
|
|
5
|
-
"version": "1.0.4-beta.
|
|
5
|
+
"version": "1.0.4-beta.13",
|
|
6
6
|
"publisher": "noyrax",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
package/scripts/verify-adrs.js
CHANGED
|
@@ -154,45 +154,136 @@ function extractClaimsFromAdr(adrPath) {
|
|
|
154
154
|
return claims;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Lädt die Path-Alias-Map aus .database-plugin/path-aliases.json
|
|
159
|
+
*/
|
|
160
|
+
function loadAliasMap(workspaceRoot) {
|
|
161
|
+
const aliasMapPath = path.join(workspaceRoot, '.database-plugin', 'path-aliases.json');
|
|
162
|
+
if (fs.existsSync(aliasMapPath)) {
|
|
163
|
+
try {
|
|
164
|
+
const content = fs.readFileSync(aliasMapPath, 'utf-8');
|
|
165
|
+
return JSON.parse(content);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
// Ignore errors loading alias map
|
|
168
|
+
return {};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return {};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Resolved einen Pfad mit Hilfe der Alias-Map
|
|
176
|
+
*/
|
|
177
|
+
function resolvePathWithAlias(filePath, workspaceRoot, aliasMap) {
|
|
178
|
+
// Normalisiere den Pfad (forward slashes)
|
|
179
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
180
|
+
|
|
181
|
+
// Prüfe ob es einen Alias gibt
|
|
182
|
+
if (aliasMap[normalized]) {
|
|
183
|
+
return path.join(workspaceRoot, aliasMap[normalized]);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Fallback: Original-Pfad
|
|
187
|
+
return path.join(workspaceRoot, filePath);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Findet src/ Verzeichnis mit Hilfe der Alias-Map
|
|
192
|
+
*/
|
|
193
|
+
function findSrcDirectory(workspaceRoot, aliasMap) {
|
|
194
|
+
// Standard: src/ im Workspace-Root
|
|
195
|
+
const standardSrc = path.join(workspaceRoot, 'src');
|
|
196
|
+
if (fs.existsSync(standardSrc)) {
|
|
197
|
+
return standardSrc;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Suche in Alias-Map nach src/ Pfaden
|
|
201
|
+
for (const [alias, target] of Object.entries(aliasMap)) {
|
|
202
|
+
if (alias.startsWith('src/') || alias.includes('/src/')) {
|
|
203
|
+
// Extrahiere das Plugin-Root aus dem Target
|
|
204
|
+
const targetParts = target.split('/');
|
|
205
|
+
const srcIndex = targetParts.indexOf('src');
|
|
206
|
+
if (srcIndex > 0) {
|
|
207
|
+
const pluginRoot = targetParts.slice(0, srcIndex).join('/');
|
|
208
|
+
const srcDir = path.join(workspaceRoot, pluginRoot, 'src');
|
|
209
|
+
if (fs.existsSync(srcDir)) {
|
|
210
|
+
return srcDir;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Suche rekursiv nach src/ Verzeichnissen (max. 2 Ebenen tief)
|
|
217
|
+
try {
|
|
218
|
+
const searchDirs = [
|
|
219
|
+
workspaceRoot,
|
|
220
|
+
...fs.readdirSync(workspaceRoot, { withFileTypes: true })
|
|
221
|
+
.filter(dirent => dirent.isDirectory() && !dirent.name.startsWith('.') && dirent.name !== 'node_modules')
|
|
222
|
+
.map(dirent => path.join(workspaceRoot, dirent.name))
|
|
223
|
+
];
|
|
224
|
+
|
|
225
|
+
for (const searchDir of searchDirs) {
|
|
226
|
+
const srcDir = path.join(searchDir, 'src');
|
|
227
|
+
if (fs.existsSync(srcDir)) {
|
|
228
|
+
return srcDir;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
} catch (error) {
|
|
232
|
+
// Ignore errors
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
|
|
157
238
|
/**
|
|
158
239
|
* Verifiziert einen Claim
|
|
159
240
|
*/
|
|
160
241
|
function verifyClaim(claim, workspaceRoot) {
|
|
242
|
+
// Lade Alias-Map
|
|
243
|
+
const aliasMap = loadAliasMap(workspaceRoot);
|
|
244
|
+
|
|
161
245
|
if (claim.type === 'file-exists') {
|
|
162
|
-
|
|
163
|
-
const
|
|
246
|
+
// Versuche zuerst mit Alias-Map
|
|
247
|
+
const resolvedPath = resolvePathWithAlias(claim.file, workspaceRoot, aliasMap);
|
|
248
|
+
const exists = fs.existsSync(resolvedPath);
|
|
164
249
|
|
|
165
250
|
if (!exists) {
|
|
166
|
-
//
|
|
167
|
-
const
|
|
168
|
-
const
|
|
251
|
+
// Fallback: Original-Pfad
|
|
252
|
+
const fullPath = path.join(workspaceRoot, claim.file);
|
|
253
|
+
const existsOriginal = fs.existsSync(fullPath);
|
|
169
254
|
|
|
170
|
-
if (
|
|
171
|
-
|
|
255
|
+
if (!existsOriginal) {
|
|
256
|
+
// Prüfe ob es als .js in out/ existiert (kompilierte Version)
|
|
257
|
+
const jsPath = fullPath.replace(/^src\//, 'out/').replace(/\.ts$/, '.js');
|
|
258
|
+
const jsExists = fs.existsSync(path.join(workspaceRoot, jsPath));
|
|
259
|
+
|
|
260
|
+
if (jsExists) {
|
|
261
|
+
warnings.push({
|
|
262
|
+
adr: claim.adr,
|
|
263
|
+
line: claim.line,
|
|
264
|
+
claim: `File ${claim.file} exists as compiled ${jsPath}, but source not found`,
|
|
265
|
+
type: 'file-exists'
|
|
266
|
+
});
|
|
267
|
+
return true; // Akzeptabel
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
errors.push({
|
|
172
271
|
adr: claim.adr,
|
|
173
272
|
line: claim.line,
|
|
174
|
-
claim: `File ${claim.file}
|
|
273
|
+
claim: `File ${claim.file} does not exist`,
|
|
175
274
|
type: 'file-exists'
|
|
176
275
|
});
|
|
177
|
-
return
|
|
276
|
+
return false;
|
|
178
277
|
}
|
|
179
|
-
|
|
180
|
-
errors.push({
|
|
181
|
-
adr: claim.adr,
|
|
182
|
-
line: claim.line,
|
|
183
|
-
claim: `File ${claim.file} does not exist`,
|
|
184
|
-
type: 'file-exists'
|
|
185
|
-
});
|
|
186
|
-
return false;
|
|
187
278
|
}
|
|
188
279
|
return true;
|
|
189
280
|
}
|
|
190
281
|
|
|
191
282
|
if (claim.type === 'function-exists') {
|
|
192
283
|
try {
|
|
193
|
-
//
|
|
194
|
-
const srcDir =
|
|
195
|
-
if (!
|
|
284
|
+
// Finde src/ Verzeichnis mit Hilfe der Alias-Map
|
|
285
|
+
const srcDir = findSrcDirectory(workspaceRoot, aliasMap);
|
|
286
|
+
if (!srcDir) {
|
|
196
287
|
warnings.push({
|
|
197
288
|
adr: claim.adr,
|
|
198
289
|
line: claim.line,
|
|
@@ -16,6 +16,39 @@ const { execSync } = require('child_process');
|
|
|
16
16
|
const errors = [];
|
|
17
17
|
const warnings = [];
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Lädt die Path-Alias-Map aus .database-plugin/path-aliases.json
|
|
21
|
+
*/
|
|
22
|
+
function loadAliasMap(workspaceRoot) {
|
|
23
|
+
const aliasMapPath = path.join(workspaceRoot, '.database-plugin', 'path-aliases.json');
|
|
24
|
+
if (fs.existsSync(aliasMapPath)) {
|
|
25
|
+
try {
|
|
26
|
+
const content = fs.readFileSync(aliasMapPath, 'utf-8');
|
|
27
|
+
return JSON.parse(content);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
// Ignore errors loading alias map
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Resolved einen Pfad mit Hilfe der Alias-Map
|
|
38
|
+
*/
|
|
39
|
+
function resolvePathWithAlias(filePath, workspaceRoot, aliasMap) {
|
|
40
|
+
// Normalisiere den Pfad (forward slashes)
|
|
41
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
42
|
+
|
|
43
|
+
// Prüfe ob es einen Alias gibt
|
|
44
|
+
if (aliasMap[normalized]) {
|
|
45
|
+
return path.join(workspaceRoot, aliasMap[normalized]);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Fallback: Original-Pfad
|
|
49
|
+
return path.join(workspaceRoot, filePath);
|
|
50
|
+
}
|
|
51
|
+
|
|
19
52
|
/**
|
|
20
53
|
* Findet ein Verzeichnis durch intelligente Suche.
|
|
21
54
|
* Sucht im gegebenen Verzeichnis und in Parent-Verzeichnissen (max. 5 Ebenen).
|
|
@@ -55,8 +88,25 @@ function findDirectoryOrFile(startDir, targetPath, maxDepth = 5) {
|
|
|
55
88
|
function checkMcpToSrcImports(workspaceRoot) {
|
|
56
89
|
console.log('🔍 Checking for invalid imports from mcp/ to src/...');
|
|
57
90
|
|
|
91
|
+
// Lade Alias-Map
|
|
92
|
+
const aliasMap = loadAliasMap(workspaceRoot);
|
|
93
|
+
|
|
58
94
|
// Suche mcp/src relativ zu workspaceRoot
|
|
59
95
|
let mcpSrcDir = findDirectoryOrFile(workspaceRoot, 'mcp/src');
|
|
96
|
+
if (!mcpSrcDir) {
|
|
97
|
+
// Versuche mit Alias-Map
|
|
98
|
+
const aliasKeys = Object.keys(aliasMap);
|
|
99
|
+
for (const alias of aliasKeys) {
|
|
100
|
+
if (alias.includes('mcp/src') || alias.includes('/mcp/src')) {
|
|
101
|
+
const resolved = resolvePathWithAlias(alias, workspaceRoot, aliasMap);
|
|
102
|
+
if (fs.existsSync(resolved)) {
|
|
103
|
+
mcpSrcDir = resolved;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
60
110
|
if (!mcpSrcDir) {
|
|
61
111
|
// Fallback: Versuche __dirname + '/..' (Plugin-interne Suche)
|
|
62
112
|
const fallbackRoot = path.join(__dirname, '..');
|
|
@@ -15,6 +15,69 @@ const { execSync } = require('child_process');
|
|
|
15
15
|
const errors = [];
|
|
16
16
|
const warnings = [];
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Lädt die Path-Alias-Map aus .database-plugin/path-aliases.json
|
|
20
|
+
*/
|
|
21
|
+
function loadAliasMap(workspaceRoot) {
|
|
22
|
+
const aliasMapPath = path.join(workspaceRoot, '.database-plugin', 'path-aliases.json');
|
|
23
|
+
if (fs.existsSync(aliasMapPath)) {
|
|
24
|
+
try {
|
|
25
|
+
const content = fs.readFileSync(aliasMapPath, 'utf-8');
|
|
26
|
+
return JSON.parse(content);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
// Ignore errors loading alias map
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Resolved einen Pfad mit Hilfe der Alias-Map
|
|
37
|
+
*/
|
|
38
|
+
function resolvePathWithAlias(filePath, workspaceRoot, aliasMap) {
|
|
39
|
+
// Normalisiere den Pfad (forward slashes)
|
|
40
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
41
|
+
|
|
42
|
+
// Prüfe ob es einen Alias gibt
|
|
43
|
+
if (aliasMap[normalized]) {
|
|
44
|
+
return path.join(workspaceRoot, aliasMap[normalized]);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Fallback: Original-Pfad
|
|
48
|
+
return path.join(workspaceRoot, filePath);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Findet src/ Verzeichnis mit Hilfe der Alias-Map
|
|
53
|
+
*/
|
|
54
|
+
function findSrcDirectoryWithAlias(startDir, workspaceRoot, aliasMap, maxDepth = 5) {
|
|
55
|
+
// Standard: src/ im Workspace-Root
|
|
56
|
+
const standardSrc = path.join(workspaceRoot, 'src');
|
|
57
|
+
if (fs.existsSync(standardSrc)) {
|
|
58
|
+
return standardSrc;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Suche in Alias-Map nach src/ Pfaden
|
|
62
|
+
for (const [alias, target] of Object.entries(aliasMap)) {
|
|
63
|
+
if (alias.startsWith('src/') || alias.includes('/src/')) {
|
|
64
|
+
// Extrahiere das Plugin-Root aus dem Target
|
|
65
|
+
const targetParts = target.split('/');
|
|
66
|
+
const srcIndex = targetParts.indexOf('src');
|
|
67
|
+
if (srcIndex > 0) {
|
|
68
|
+
const pluginRoot = targetParts.slice(0, srcIndex).join('/');
|
|
69
|
+
const srcDir = path.join(workspaceRoot, pluginRoot, 'src');
|
|
70
|
+
if (fs.existsSync(srcDir)) {
|
|
71
|
+
return srcDir;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Fallback: Original findSrcDirectory
|
|
78
|
+
return findSrcDirectory(startDir, maxDepth);
|
|
79
|
+
}
|
|
80
|
+
|
|
18
81
|
/**
|
|
19
82
|
* Sammelt alle TypeScript-Dateien rekursiv
|
|
20
83
|
*/
|
|
@@ -126,7 +189,7 @@ function findSrcDirectory(startDir, maxDepth = 5) {
|
|
|
126
189
|
/**
|
|
127
190
|
* Prüft ob ein Import verfügbar ist
|
|
128
191
|
*/
|
|
129
|
-
function checkImport(importPath, importedName, fromFile, workspaceRoot) {
|
|
192
|
+
function checkImport(importPath, importedName, fromFile, workspaceRoot, aliasMap) {
|
|
130
193
|
|
|
131
194
|
// Resolve import path
|
|
132
195
|
let targetFile;
|
|
@@ -148,6 +211,14 @@ function checkImport(importPath, importedName, fromFile, workspaceRoot) {
|
|
|
148
211
|
targetFile = path.join(targetFile, 'index.js');
|
|
149
212
|
}
|
|
150
213
|
}
|
|
214
|
+
|
|
215
|
+
// Versuche mit Alias-Map, wenn Datei nicht gefunden wurde
|
|
216
|
+
if (!fs.existsSync(targetFile) && aliasMap) {
|
|
217
|
+
const relativePath = path.relative(workspaceRoot, targetFile).replace(/\\/g, '/');
|
|
218
|
+
if (aliasMap[relativePath]) {
|
|
219
|
+
targetFile = path.join(workspaceRoot, aliasMap[relativePath]);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
151
222
|
} else {
|
|
152
223
|
// Node module import - skip for now
|
|
153
224
|
return true;
|
|
@@ -187,7 +258,7 @@ function checkImport(importPath, importedName, fromFile, workspaceRoot) {
|
|
|
187
258
|
/**
|
|
188
259
|
* Prüft alle Imports in einer Datei
|
|
189
260
|
*/
|
|
190
|
-
function checkFileImports(filePath, workspaceRoot) {
|
|
261
|
+
function checkFileImports(filePath, workspaceRoot, aliasMap) {
|
|
191
262
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
192
263
|
const lines = content.split('\n');
|
|
193
264
|
|
|
@@ -230,7 +301,7 @@ function checkFileImports(filePath, workspaceRoot) {
|
|
|
230
301
|
|
|
231
302
|
// Check each imported name
|
|
232
303
|
importedNames.forEach(name => {
|
|
233
|
-
checkImport(importPath, name, filePath, workspaceRoot);
|
|
304
|
+
checkImport(importPath, name, filePath, workspaceRoot, aliasMap);
|
|
234
305
|
});
|
|
235
306
|
}
|
|
236
307
|
}
|
|
@@ -267,14 +338,17 @@ function main() {
|
|
|
267
338
|
}
|
|
268
339
|
}
|
|
269
340
|
|
|
270
|
-
//
|
|
271
|
-
const
|
|
341
|
+
// Lade Alias-Map
|
|
342
|
+
const aliasMap = loadAliasMap(workspaceRoot);
|
|
343
|
+
|
|
344
|
+
// src/ Verzeichnis finden (intelligente Suche mit Alias-Map)
|
|
345
|
+
const srcDir = findSrcDirectoryWithAlias(workspaceRoot, workspaceRoot, aliasMap);
|
|
272
346
|
if (!srcDir) {
|
|
273
347
|
console.log('⚠️ src/ directory not found, skipping verification');
|
|
274
348
|
console.log(` Searched from: ${workspaceRoot}`);
|
|
275
349
|
process.exit(0);
|
|
276
350
|
}
|
|
277
|
-
|
|
351
|
+
|
|
278
352
|
// workspaceRoot auf Basis des gefundenen src/ korrigieren
|
|
279
353
|
workspaceRoot = path.dirname(srcDir);
|
|
280
354
|
|
|
@@ -285,7 +359,7 @@ function main() {
|
|
|
285
359
|
|
|
286
360
|
let checkedFiles = 0;
|
|
287
361
|
for (const file of files) {
|
|
288
|
-
checkFileImports(file, workspaceRoot);
|
|
362
|
+
checkFileImports(file, workspaceRoot, aliasMap);
|
|
289
363
|
checkedFiles++;
|
|
290
364
|
|
|
291
365
|
if (checkedFiles % 10 === 0) {
|