entkapp 4.5.1 → 5.1.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/bin/cli.js +4 -4
- package/entkapp/config.json +0 -1
- package/package.json +5 -6
- package/src/EngineContext.js +276 -78
- package/src/analyzers/OxcAnalyzer.js +8 -380
- package/src/api/HeadlessAPI.js +1 -1
- package/src/api/PluginSDK.js +23 -187
- package/src/ast/ASTAnalyzer.js +481 -252
- package/src/ast/AdvancedAnalysis.js +6 -5
- package/src/ast/BarrelParser.js +39 -30
- package/src/ast/DeadCodeDetector.js +30 -18
- package/src/ast/MagicDetector.js +1 -1
- package/src/ast/OxcAnalyzer.js +335 -273
- package/src/index.js +279 -365
- package/src/performance/GraphCache.js +21 -2
- package/src/performance/WorkerPool.js +11 -1
- package/src/performance/WorkerTaskRunner.js +72 -25
- package/src/plugins/PluginRegistry.js +5 -16
- package/src/plugins/ecosystems/GenericPlugins.js +61 -0
- package/src/refractor/TransactionManager.js +3 -136
- package/src/refractor/TypeIntegrity.js +2 -73
- package/src/resolution/CircularDetector.js +44 -44
- package/src/resolution/ConfigLoader.js +2 -85
- package/src/resolution/DepencyResolver.js +28 -121
- package/src/resolution/EntryPointDetector.js +134 -0
- package/src/resolution/PathMapper.js +31 -107
- package/src/resolution/TSConfigLoader.js +76 -0
- package/src/resolution/WorkSpaceGraph.js +6 -472
- package/src/resolution/WorkspaceDiagnostic.js +3 -57
- package/src/plugins/KnipAdapter.js +0 -106
|
@@ -1,125 +1,49 @@
|
|
|
1
|
-
import fs from 'fs
|
|
1
|
+
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Advanced TSConfig / JSConfig Compilation Path Alias Mapper
|
|
6
|
-
* Resolves deeply nested route mappings, wildcards, and base URL overrides.
|
|
7
|
-
*/
|
|
8
4
|
export class PathMapper {
|
|
9
|
-
constructor(context) {
|
|
10
|
-
this.context = context;
|
|
11
|
-
this.baseUrl = '.';
|
|
12
|
-
this.absoluteBaseUrl = context.cwd;
|
|
13
|
-
this.mappings = []; // Collection of { prefix, suffix, targets[] }
|
|
5
|
+
constructor(context) {
|
|
6
|
+
this.context = context;
|
|
14
7
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
* @param {string} tsconfigFilename - Target designator (typically tsconfig.json)
|
|
19
|
-
*/
|
|
20
|
-
async loadMappings(tsconfigFilename = 'tsconfig.json') {
|
|
21
|
-
const configPath = path.resolve(this.context.cwd, tsconfigFilename);
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
await fs.access(configPath);
|
|
25
|
-
const rawText = await fs.readFile(configPath, 'utf8');
|
|
26
|
-
|
|
27
|
-
// Strip inline single-line and block comments before parsing
|
|
28
|
-
// Improved regex to handle more edge cases in tsconfig comments
|
|
29
|
-
const jsonCleanText = rawText
|
|
30
|
-
.replace(/\/\*[\s\S]*?\*\/|(?<=[^\\:])\/\/.*$/gm, '')
|
|
31
|
-
.replace(/,(\s*[\]}])/g, '$1'); // Remove trailing commas
|
|
32
|
-
|
|
33
|
-
const tsconfig = JSON.parse(jsonCleanText);
|
|
34
|
-
|
|
35
|
-
if (!tsconfig.compilerOptions) return;
|
|
36
|
-
|
|
37
|
-
const opts = tsconfig.compilerOptions;
|
|
38
|
-
|
|
39
|
-
// v6 Path Resolution Fix (Knip Issue #1794)
|
|
40
|
-
// Ensure baseUrl is correctly resolved relative to the tsconfig file location
|
|
41
|
-
const configDir = path.dirname(configPath);
|
|
42
|
-
if (opts.baseUrl) {
|
|
43
|
-
this.baseUrl = opts.baseUrl;
|
|
44
|
-
this.absoluteBaseUrl = path.resolve(configDir, this.baseUrl);
|
|
45
|
-
} else {
|
|
46
|
-
this.absoluteBaseUrl = configDir;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (opts.paths) {
|
|
50
|
-
for (const [aliasPattern, targetArrays] of Object.entries(opts.paths)) {
|
|
51
|
-
this.registerPatternRule(aliasPattern, targetArrays);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
} catch (error) {
|
|
55
|
-
if (this.context.verbose) {
|
|
56
|
-
console.warn(`⚠️ [PathMapper Override] Proceeding without custom path configurations. Source: ${error.message}`);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
8
|
+
|
|
9
|
+
async loadMappings() {
|
|
10
|
+
// Hier können später tsconfig-Pfade geladen werden
|
|
59
11
|
}
|
|
60
12
|
|
|
61
13
|
/**
|
|
62
|
-
*
|
|
14
|
+
* Resolves physical module paths on disk, translating modern .js imports
|
|
15
|
+
* back to their actual TypeScript source files.
|
|
16
|
+
* @param {string} p - The target module specifier or absolute path
|
|
63
17
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
18
|
+
resolvePath(p) {
|
|
19
|
+
if (!p || typeof p !== 'string') return p;
|
|
66
20
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
targets: targets.map(t => path.normalize(t))
|
|
72
|
-
});
|
|
73
|
-
return;
|
|
21
|
+
// FIX 1: Wenn der Import auf .js endet, übersetze ihn für die Suche auf .ts
|
|
22
|
+
if (p.endsWith('.js')) {
|
|
23
|
+
const tsPath = p.slice(0, -3) + '.ts';
|
|
24
|
+
if (fs.existsSync(tsPath)) return tsPath;
|
|
74
25
|
}
|
|
75
26
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
prefix,
|
|
82
|
-
suffix,
|
|
83
|
-
targets: targets.map(t => path.normalize(t))
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Resolves a raw import specifier against mapped path patterns.
|
|
89
|
-
* @param {string} specifier - Raw text from import declaration (e.g., '@ui/button')
|
|
90
|
-
* @returns {Array<string>} Candidates of absolute filesystem paths to try resolving
|
|
91
|
-
*/
|
|
92
|
-
resolveCandidatePaths(specifier) {
|
|
93
|
-
const matchingCandidates = [];
|
|
94
|
-
|
|
95
|
-
for (const rule of this.mappings) {
|
|
96
|
-
if (rule.isExact) {
|
|
97
|
-
if (specifier === rule.pattern) {
|
|
98
|
-
rule.targets.forEach(target => {
|
|
99
|
-
matchingCandidates.push(path.resolve(this.absoluteBaseUrl, target));
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
} else {
|
|
103
|
-
// Evaluate wildcard pattern matches
|
|
104
|
-
if (specifier.startsWith(rule.prefix) && specifier.endsWith(rule.suffix)) {
|
|
105
|
-
const extractedWildcardContent = specifier.slice(
|
|
106
|
-
rule.prefix.length,
|
|
107
|
-
specifier.length - rule.suffix.length
|
|
108
|
-
);
|
|
27
|
+
// FIX 2: Wenn der Import auf .jsx endet, übersetze ihn für die Suche auf .tsx
|
|
28
|
+
if (p.endsWith('.jsx')) {
|
|
29
|
+
const tsxPath = p.slice(0, -4) + '.tsx';
|
|
30
|
+
if (fs.existsSync(tsxPath)) return tsxPath;
|
|
31
|
+
}
|
|
109
32
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
33
|
+
// FIX 3: Unterstützung für Verzeichnis-Imports (z.B. ./adapters -> ./adapters/index.ts)
|
|
34
|
+
try {
|
|
35
|
+
const stat = fs.statSync(p);
|
|
36
|
+
if (stat.isDirectory()) {
|
|
37
|
+
const extensions = ['.ts', '.tsx', '.js', '.jsx'];
|
|
38
|
+
for (const ext of extensions) {
|
|
39
|
+
const indexPath = path.join(p, `index${ext}`);
|
|
40
|
+
if (fs.existsSync(indexPath)) return indexPath;
|
|
114
41
|
}
|
|
115
42
|
}
|
|
43
|
+
} catch {
|
|
44
|
+
// Datei existiert nicht oder ist kein Verzeichnis, fahre mit Standard fort
|
|
116
45
|
}
|
|
117
46
|
|
|
118
|
-
|
|
119
|
-
if (!specifier.startsWith('.') && !path.isAbsolute(specifier)) {
|
|
120
|
-
matchingCandidates.push(path.resolve(this.absoluteBaseUrl, specifier));
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return matchingCandidates;
|
|
47
|
+
return p;
|
|
124
48
|
}
|
|
125
49
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import ts from 'typescript';
|
|
4
|
+
|
|
5
|
+
export class TSConfigLoader {
|
|
6
|
+
constructor(targetDir) {
|
|
7
|
+
this.targetDir = targetDir;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Lädt und parst die tsconfig.json.
|
|
12
|
+
* @returns {Object|null} Parsed config oder null.
|
|
13
|
+
*/
|
|
14
|
+
load() {
|
|
15
|
+
const configPath = path.join(this.targetDir, 'tsconfig.json');
|
|
16
|
+
if (!fs.existsSync(configPath)) return null;
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
20
|
+
const result = ts.parseConfigFileTextWithComments(configPath, content);
|
|
21
|
+
|
|
22
|
+
if (result.error) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const parsed = ts.parseJsonConfigFileContent(
|
|
27
|
+
result.config,
|
|
28
|
+
ts.sys,
|
|
29
|
+
this.targetDir
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return parsed;
|
|
33
|
+
} catch (e) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Erstellt eine Mapping-Funktion für Aliases aus der tsconfig.
|
|
40
|
+
* @param {Object} parsedConfig
|
|
41
|
+
* @returns {Function} Mapper function.
|
|
42
|
+
*/
|
|
43
|
+
getAliasMapper(parsedConfig) {
|
|
44
|
+
if (!parsedConfig || !parsedConfig.options || !parsedConfig.options.paths) {
|
|
45
|
+
return (source) => source;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const { paths, baseUrl } = parsedConfig.options;
|
|
49
|
+
const base = baseUrl ? path.resolve(this.targetDir, baseUrl) : this.targetDir;
|
|
50
|
+
|
|
51
|
+
return (source) => {
|
|
52
|
+
for (const pattern in paths) {
|
|
53
|
+
const regexPattern = pattern.replace(/\*/, '(.*)');
|
|
54
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
55
|
+
const match = source.match(regex);
|
|
56
|
+
|
|
57
|
+
if (match) {
|
|
58
|
+
const replacements = paths[pattern];
|
|
59
|
+
for (const replacement of replacements) {
|
|
60
|
+
const resolvedReplacement = replacement.replace(/\*/, match[1]);
|
|
61
|
+
const fullPath = path.resolve(base, resolvedReplacement);
|
|
62
|
+
|
|
63
|
+
// Prüfe ob Datei existiert
|
|
64
|
+
const extensions = ['', '.ts', '.tsx', '.js', '.jsx'];
|
|
65
|
+
for (const ext of extensions) {
|
|
66
|
+
if (fs.existsSync(fullPath + ext)) {
|
|
67
|
+
return fullPath + ext;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return source;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|