entkapp 5.4.0 → 5.6.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.
Files changed (76) hide show
  1. package/README.md +7 -1
  2. package/bin/cli.js +117 -58
  3. package/bin/cli.mjs +175 -0
  4. package/index.cjs +18 -0
  5. package/index.mjs +51 -0
  6. package/package.json +7 -6
  7. package/src/EngineContext.js +0 -6
  8. package/src/EngineContext.mjs +428 -0
  9. package/src/Initializer.mjs +82 -0
  10. package/src/analyzers/CodeSmellAnalyzer.mjs +106 -0
  11. package/src/analyzers/OxcAnalyzer.mjs +11 -0
  12. package/src/api/HeadlessAPI.js +31 -16
  13. package/src/api/HeadlessAPI.mjs +369 -0
  14. package/src/api/PluginSDK.mjs +135 -0
  15. package/src/ast/ASTAnalyzer.js +23 -97
  16. package/src/ast/ASTAnalyzer.mjs +742 -0
  17. package/src/ast/AdvancedAnalysis.mjs +586 -0
  18. package/src/ast/BarrelParser.mjs +230 -0
  19. package/src/ast/DeadCodeDetector.js +7 -5
  20. package/src/ast/DeadCodeDetector.mjs +92 -0
  21. package/src/ast/MagicDetector.js +43 -23
  22. package/src/ast/MagicDetector.mjs +203 -0
  23. package/src/ast/OxcAnalyzer.js +27 -190
  24. package/src/ast/OxcAnalyzer.mjs +188 -0
  25. package/src/ast/SecretScanner.mjs +374 -0
  26. package/src/healing/GitSandbox.mjs +82 -0
  27. package/src/healing/SelfHealer.mjs +48 -0
  28. package/src/index.js +41 -88
  29. package/src/index.mjs +1176 -0
  30. package/src/performance/GraphCache.js +0 -27
  31. package/src/performance/GraphCache.mjs +108 -0
  32. package/src/performance/SupplyChainGuard.mjs +92 -0
  33. package/src/performance/WorkerPool.js +4 -22
  34. package/src/performance/WorkerPool.mjs +132 -0
  35. package/src/performance/WorkerTaskRunner.js +0 -26
  36. package/src/performance/WorkerTaskRunner.mjs +144 -0
  37. package/src/plugins/BasePlugin.js +27 -16
  38. package/src/plugins/BasePlugin.mjs +240 -0
  39. package/src/plugins/PluginRegistry.js +0 -44
  40. package/src/plugins/PluginRegistry.mjs +203 -0
  41. package/src/plugins/ecosystems/BackendServices.mjs +197 -0
  42. package/src/plugins/ecosystems/GenericPlugins.mjs +142 -0
  43. package/src/plugins/ecosystems/ModernFrameworks.mjs +162 -0
  44. package/src/plugins/ecosystems/MorePlugins.mjs +562 -0
  45. package/src/plugins/ecosystems/NewPlugins.mjs +526 -0
  46. package/src/plugins/ecosystems/NextJsPlugin.mjs +45 -0
  47. package/src/plugins/ecosystems/PluginLoader.mjs +193 -0
  48. package/src/plugins/ecosystems/TypeScriptPlugin.mjs +56 -0
  49. package/src/plugins/ecosystems/UltimateBundle.js +0 -259
  50. package/src/plugins/ecosystems/UltimateBundle.mjs +1182 -0
  51. package/src/refractor/ImpactAnalyzer.mjs +92 -0
  52. package/src/refractor/SourceRewriter.mjs +86 -0
  53. package/src/refractor/TransactionManager.mjs +5 -0
  54. package/src/refractor/TypeIntegrity.mjs +4 -0
  55. package/src/resolution/BuildOrchestrator.mjs +46 -0
  56. package/src/resolution/CircularDetector.mjs +91 -0
  57. package/src/resolution/ConfigGenerator.mjs +83 -0
  58. package/src/resolution/ConfigLoader.js +26 -190
  59. package/src/resolution/ConfigLoader.mjs +94 -0
  60. package/src/resolution/DepencyResolver.mjs +66 -0
  61. package/src/resolution/DependencyFixer.mjs +88 -0
  62. package/src/resolution/DependencyProfiler.mjs +286 -0
  63. package/src/resolution/EntryPointDetector.mjs +134 -0
  64. package/src/resolution/FrameworkConfigParser.mjs +119 -0
  65. package/src/resolution/GraphAnalyzer.js +1 -65
  66. package/src/resolution/GraphAnalyzer.mjs +80 -0
  67. package/src/resolution/MigrationAnalyzer.mjs +60 -0
  68. package/src/resolution/PathMapper.js +0 -81
  69. package/src/resolution/PathMapper.mjs +82 -0
  70. package/src/resolution/TSConfigLoader.js +1 -3
  71. package/src/resolution/TSConfigLoader.mjs +162 -0
  72. package/src/resolution/WorkSpaceGraph.js +89 -260
  73. package/src/resolution/WorkSpaceGraph.mjs +183 -0
  74. package/src/resolution/WorkspaceDiagnostic.mjs +139 -0
  75. package/test.js +76 -0
  76. package/wrangler.toml +6 -0
@@ -0,0 +1,230 @@
1
+ import ts from 'typescript';
2
+ import fs from 'fs/promises';
3
+
4
+ /**
5
+ * Enterprise Wildcard Optimization & Flattening Layer for Barrel Operations
6
+ * Traces unreferenced paths through redistribution entries.
7
+ */
8
+ export class BarrelParser {
9
+ constructor(context, resolver) {
10
+ this.context = context; // Enthält globale Konfigurationen (z.B. context.entrypoints)
11
+ this.resolver = resolver;
12
+ this.cachedSpecifications = new Map();
13
+ }
14
+
15
+ /**
16
+ * Compiles the structural export layout for a specific index or barrel target.
17
+ * @param {string} filePath - Absolute path to on-disk target element
18
+ */
19
+ async parseBarrelSpecification(filePath) {
20
+ if (this.cachedSpecifications.has(filePath)) {
21
+ return this.cachedSpecifications.get(filePath);
22
+ }
23
+
24
+ const specification = {
25
+ isBarrelInstance: false,
26
+ isApplicationEntrypoint: false, // FIX: Schutzschicht für Einstiegspunkte gegen Fehldetektion
27
+ wildcardExports: new Set(), // export * from './module';
28
+ namespacedWildcardExports: new Map(), // export * as Utils from './module';
29
+ forwardedNamedExports: new Map(), // export { token as alias } from './module';
30
+ declaredLocalExports: new Set() // export const a = 1;
31
+ };
32
+
33
+ // FIX: Überprüfe, ob die aktuelle Datei als App-Einstiegspunkt deklariert ist
34
+ if (this.context && this.context.entrypoints) {
35
+ const isEntry = this.context.entrypoints.some(entry =>
36
+ this.resolver.resolveModulePath(filePath, entry) === filePath || entry === filePath
37
+ );
38
+ if (isEntry) {
39
+ specification.isApplicationEntrypoint = true;
40
+ }
41
+ }
42
+
43
+ try {
44
+ const code = await fs.readFile(filePath, 'utf8');
45
+ const sourceFile = ts.createSourceFile(filePath, code, ts.ScriptTarget.Latest, true);
46
+
47
+ this.harvestExportSignatures(sourceFile, specification);
48
+
49
+ // FIX: Eine Datei ist NUR DANN ein rein kosmetisches Barrel, wenn sie Re-Exports besitzt
50
+ // UND NICHT der geschützte Haupteinstiegspunkt (Entrypoint) der Anwendung ist!
51
+ if (!specification.isApplicationEntrypoint && (
52
+ specification.wildcardExports.size > 0 ||
53
+ specification.namespacedWildcardExports.size > 0 ||
54
+ specification.forwardedNamedExports.size > 0
55
+ )) {
56
+ specification.isBarrelInstance = true;
57
+ }
58
+
59
+ this.cachedSpecifications.set(filePath, specification);
60
+ return specification;
61
+ } catch {
62
+ return specification; // Error-State fällt auf sicheres Standard-Layout zurück
63
+ }
64
+ }
65
+
66
+ harvestExportSignatures(node, spec) {
67
+ if (!node) return;
68
+
69
+ switch (node.kind) {
70
+ case ts.SyntaxKind.ExportDeclaration: {
71
+ const targetSpecifier = node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)
72
+ ? node.moduleSpecifier.text
73
+ : null;
74
+
75
+ if (targetSpecifier) {
76
+ if (!node.exportClause) {
77
+ // Standard Wildcard Transfer: export * from './module';
78
+ spec.wildcardExports.add(targetSpecifier);
79
+ } else if (ts.isNamespaceExport(node.exportClause)) {
80
+ // Namespaced Wildcard Transfer: export * as Core from './module';
81
+ const namespaceAlias = node.exportClause.name.text;
82
+ spec.namespacedWildcardExports.set(namespaceAlias, targetSpecifier);
83
+ } else if (ts.isNamedExports(node.exportClause)) {
84
+ // Selective Re-export Forwarding: export { x, y as z } from './module';
85
+ node.exportClause.elements.forEach(element => {
86
+ const originalSymbol = element.propertyName ? element.propertyName.text : element.name.text;
87
+ const exposedAlias = element.name.text;
88
+ spec.forwardedNamedExports.set(exposedAlias, {
89
+ targetModule: targetSpecifier,
90
+ sourceSymbol: originalSymbol
91
+ });
92
+ });
93
+ }
94
+ }
95
+ break;
96
+ }
97
+
98
+ // Track items declared directly within the file boundary
99
+ case ts.SyntaxKind.FunctionDeclaration:
100
+ case ts.SyntaxKind.ClassDeclaration:
101
+ case ts.SyntaxKind.InterfaceDeclaration:
102
+ case ts.SyntaxKind.TypeAliasDeclaration:
103
+ case ts.SyntaxKind.EnumDeclaration: {
104
+ if (node.modifiers && node.modifiers.some(m => m.kind === ts.SyntaxKind.ExportKeyword)) {
105
+ if (node.name && ts.isIdentifier(node.name)) {
106
+ spec.declaredLocalExports.add(node.name.text);
107
+ }
108
+ }
109
+ break;
110
+ }
111
+
112
+ case ts.SyntaxKind.VariableStatement: {
113
+ if (node.modifiers && node.modifiers.some(m => m.kind === ts.SyntaxKind.ExportKeyword)) {
114
+ node.declarationList.declarations.forEach(decl => {
115
+ if (ts.isIdentifier(decl.name)) {
116
+ spec.declaredLocalExports.add(decl.name.text);
117
+ } else if (ts.isObjectBindingPattern(decl.name)) {
118
+ decl.name.elements.forEach(element => {
119
+ if (element.name && ts.isIdentifier(element.name)) {
120
+ spec.declaredLocalExports.add(element.name.text);
121
+ }
122
+ });
123
+ } else if (ts.isArrayBindingPattern(decl.name)) {
124
+ decl.name.elements.forEach(element => {
125
+ if (ts.isBindingElement(element) && element.name && ts.isIdentifier(element.name)) {
126
+ spec.declaredLocalExports.add(element.name.text);
127
+ }
128
+ });
129
+ }
130
+ });
131
+ }
132
+ break;
133
+ }
134
+
135
+ case ts.SyntaxKind.ExportAssignment: {
136
+ spec.declaredLocalExports.add('default');
137
+ break;
138
+ }
139
+ }
140
+
141
+ ts.forEachChild(node, child => this.harvestExportSignatures(child, spec));
142
+ }
143
+
144
+ /**
145
+ * Challenge #3 Resolution Logic. Unwraps nested redistribution links to find origin source nodes.
146
+ * @param {string} contextFilePath - Current position filename vector pointer
147
+ * @param {string} targetSymbolName - Targeted semantic variable signature name
148
+ * @param {Map} activeProjectGraph - Global active module maps directory registry
149
+ * @param {Set} [protectionStack] - Avoids cyclic validation traps inside self-referencing links
150
+ */
151
+ async determineSymbolDeclarationOrigin(contextFilePath, targetSymbolName, activeProjectGraph, protectionStack = new Set()) {
152
+ if (protectionStack.has(contextFilePath)) {
153
+ return { originFile: contextFilePath, originSymbol: targetSymbolName };
154
+ }
155
+ protectionStack.add(contextFilePath);
156
+
157
+ const spec = await this.parseBarrelSpecification(contextFilePath);
158
+ if (!spec.isBarrelInstance) {
159
+ return { originFile: contextFilePath, originSymbol: targetSymbolName };
160
+ }
161
+
162
+ // Rule A: Settle boundary immediately if local declaration matches token signature name
163
+ if (spec.declaredLocalExports.has(targetSymbolName)) {
164
+ return { originFile: contextFilePath, originSymbol: targetSymbolName };
165
+ }
166
+
167
+ // Rule B: Evaluate explicit named re-export mappings (export { A as B } from 'module')
168
+ if (spec.forwardedNamedExports.has(targetSymbolName)) {
169
+ const routingRule = spec.forwardedNamedExports.get(targetSymbolName);
170
+ const fullyResolvedPath = this.resolver.resolveModulePath(contextFilePath, routingRule.targetModule);
171
+ if (fullyResolvedPath) {
172
+ return this.determineSymbolDeclarationOrigin(fullyResolvedPath, routingRule.sourceSymbol, activeProjectGraph, protectionStack);
173
+ }
174
+ }
175
+
176
+ // Rule C: Evaluate structural namespace alias groupings (export * as name from 'module')
177
+ for (const [namespaceAlias, relativeModule] of spec.namespacedWildcardExports.entries()) {
178
+ if (targetSymbolName === namespaceAlias) {
179
+ const fullyResolvedPath = this.resolver.resolveModulePath(contextFilePath, relativeModule);
180
+ return { originFile: fullyResolvedPath, originSymbol: '*' };
181
+ }
182
+ if (targetSymbolName.startsWith(`${namespaceAlias}.`)) {
183
+ const originalSymbol = targetSymbolName.substring(namespaceAlias.length + 1);
184
+ const fullyResolvedPath = this.resolver.resolveModulePath(contextFilePath, relativeModule);
185
+ if (fullyResolvedPath) {
186
+ return this.determineSymbolDeclarationOrigin(fullyResolvedPath, originalSymbol, activeProjectGraph, protectionStack);
187
+ }
188
+ }
189
+ }
190
+
191
+ // Rule D: Sweep through anonymous star re-exports vectors (export * from 'module')
192
+ for (const relativePath of spec.wildcardExports) {
193
+ const fullyResolvedPath = this.resolver.resolveModulePath(contextFilePath, relativePath);
194
+
195
+ if (fullyResolvedPath) {
196
+ // Verbinde Graph-Kanten direkt während der Wildcard-Traversierung
197
+ const contextNode = activeProjectGraph.get(contextFilePath);
198
+ if (contextNode) {
199
+ contextNode.outgoingEdges.add(fullyResolvedPath);
200
+ const targetNode = activeProjectGraph.get(fullyResolvedPath);
201
+ if (targetNode) {
202
+ targetNode.incomingEdges.add(contextFilePath);
203
+ }
204
+ }
205
+
206
+ const continuousResolutionTrace = await this.determineSymbolDeclarationOrigin(
207
+ fullyResolvedPath,
208
+ targetSymbolName,
209
+ activeProjectGraph,
210
+ new Set(protectionStack) // Kopie verhindert geschwisterliche Branch-Blockaden
211
+ );
212
+
213
+ if (!continuousResolutionTrace) continue;
214
+ if (continuousResolutionTrace.originFile === contextFilePath) continue;
215
+
216
+ const originSpec = await this.parseBarrelSpecification(continuousResolutionTrace.originFile);
217
+ if (originSpec.declaredLocalExports.has(continuousResolutionTrace.originSymbol) ||
218
+ continuousResolutionTrace.originSymbol === '*') {
219
+ return continuousResolutionTrace;
220
+ }
221
+
222
+ if (originSpec.isBarrelInstance) {
223
+ return continuousResolutionTrace;
224
+ }
225
+ }
226
+ }
227
+
228
+ return { originFile: contextFilePath, originSymbol: targetSymbolName };
229
+ }
230
+ }
@@ -10,8 +10,10 @@ export class DeadCodeDetector {
10
10
  // Find all entry points
11
11
  const entryPoints = new Set();
12
12
  for (const [filePath, node] of graph.entries()) {
13
- // NIGHTMARE FIX: node.isEntry must be respected, and also check for library entries
14
- if (node.isEntry || node.isLibraryEntry || node.isNextJsRoute || node.isSvelteComponent || node.isAstroPage) {
13
+ // ADVANCED: Framework-agnostic entry point detection
14
+ // Respects explicit entries, side-effect files, and dynamic entry points
15
+ if (node.isEntry || node.isLibraryEntry || node.isDynamicEntry || node.hasSideEffects ||
16
+ node.isNextJsRoute || node.isSvelteComponent || node.isAstroPage) {
15
17
  entryPoints.add(filePath);
16
18
  }
17
19
  }
@@ -63,11 +65,11 @@ export class DeadCodeDetector {
63
65
  if (exportName === '*' || exportName === 'default') continue; // Skip wildcards for now
64
66
 
65
67
  let isUsed = false;
66
- // Check ALL nodes in the graph for usage of this symbol, not just those with edges
67
- // (Handles cases where edges might be missing or complex)
68
+ // ADVANCED: Global usage tracking including dynamic property access
68
69
  for (const [otherPath, otherNode] of graph.entries()) {
69
70
  if (otherNode.importedSymbols.has(`${filePath}:${exportName}`) ||
70
- otherNode.importedSymbols.has(`${filePath}:*`)) {
71
+ otherNode.importedSymbols.has(`${filePath}:*`) ||
72
+ otherNode.instantiatedIdentifiers.has(exportName)) {
71
73
  isUsed = true;
72
74
  break;
73
75
  }
@@ -0,0 +1,92 @@
1
+ export class DeadCodeDetector {
2
+ constructor(context) {
3
+ this.context = context;
4
+ }
5
+
6
+ detectDeadCode(graph) {
7
+ const deadFiles = [];
8
+ const deadExports = [];
9
+
10
+ // Find all entry points
11
+ const entryPoints = new Set();
12
+ for (const [filePath, node] of graph.entries()) {
13
+ // ADVANCED: Framework-agnostic entry point detection
14
+ // Respects explicit entries, side-effect files, and dynamic entry points
15
+ if (node.isEntry || node.isLibraryEntry || node.isDynamicEntry || node.hasSideEffects ||
16
+ node.isNextJsRoute || node.isSvelteComponent || node.isAstroPage) {
17
+ entryPoints.add(filePath);
18
+ }
19
+ }
20
+
21
+ // UPGRADE 5: Cycle-tolerant Graph Traversal.
22
+ // We use a robust recursive traversal with a visited set to handle cycles.
23
+ const usedFiles = new Set();
24
+ const visited = new Set();
25
+
26
+ const traverse = (filePath) => {
27
+ if (visited.has(filePath)) return;
28
+ visited.add(filePath);
29
+ usedFiles.add(filePath);
30
+
31
+ const node = graph.get(filePath);
32
+ if (node && node.outgoingEdges) {
33
+ for (const edge of node.outgoingEdges) {
34
+ traverse(edge);
35
+ }
36
+ }
37
+ };
38
+
39
+ for (const entry of entryPoints) {
40
+ traverse(entry);
41
+ }
42
+
43
+ // Identify dead files
44
+ for (const filePath of graph.keys()) {
45
+ if (!usedFiles.has(filePath)) {
46
+ deadFiles.push(filePath);
47
+ }
48
+ }
49
+
50
+ // Identify dead exports in used files
51
+ for (const filePath of usedFiles) {
52
+ const node = graph.get(filePath);
53
+ if (!node) continue;
54
+
55
+ // If it's an entry point, we consider its exports used (unless strictly configured otherwise)
56
+ // NIGHTMARE FIX: Even in entry points, we might want to find unused exports if they are not re-exported
57
+ if (node.isEntry && !node.isLibraryEntry) {
58
+ // If it's a main entry but not a library, its exports are usually unused
59
+ // unless it's a barrel file. Let's proceed to check usage.
60
+ } else if (node.isLibraryEntry) {
61
+ continue;
62
+ }
63
+
64
+ for (const [exportName, exportInfo] of node.internalExports.entries()) {
65
+ if (exportName === '*' || exportName === 'default') continue; // Skip wildcards for now
66
+
67
+ let isUsed = false;
68
+ // ADVANCED: Global usage tracking including dynamic property access
69
+ for (const [otherPath, otherNode] of graph.entries()) {
70
+ if (otherNode.importedSymbols.has(`${filePath}:${exportName}`) ||
71
+ otherNode.importedSymbols.has(`${filePath}:*`) ||
72
+ otherNode.instantiatedIdentifiers.has(exportName)) {
73
+ isUsed = true;
74
+ break;
75
+ }
76
+ }
77
+
78
+ // Additional check for library entries or index files
79
+ // NIGHTMARE FIX: Don't blindly protect 'index' files if they are not real entries
80
+ if (!isUsed && (node.isLibraryEntry)) {
81
+ isUsed = true;
82
+ }
83
+
84
+ if (!isUsed) {
85
+ deadExports.push({ file: filePath, symbol: exportName, line: exportInfo.start });
86
+ }
87
+ }
88
+ }
89
+
90
+ return { deadFiles, deadExports };
91
+ }
92
+ }
@@ -6,7 +6,15 @@ import { PluginRegistry } from '../plugins/PluginRegistry.js';
6
6
  * Ecosystem Entry Point Manifest & Dynamic Framework Router Heuristic Validator
7
7
  * Intercepts implicit conventions to handle cases where direct import statements are absent.
8
8
  * Now refactored to use a pluggable architecture.
9
- * Version 5.4.0: Added detectEntryPointsFromPlugins() for dynamic framework entry detection.
9
+ *
10
+ * Improvements over v1:
11
+ * - Extended config-file detection list (Biome, Oxlint, tsup, unbuild, etc.)
12
+ * - Next.js App Router conventions (page.tsx, layout.tsx, loading.tsx, error.tsx, etc.)
13
+ * - Remix conventions (route files under app/routes/)
14
+ * - SvelteKit conventions (+page.svelte, +layout.svelte, etc.)
15
+ * - Astro page/layout conventions
16
+ * - Common entry-point patterns (bin/, cli.ts, server.ts, main.ts, app.ts)
17
+ * - Test file patterns extended to cover Vitest workspace files
10
18
  */
11
19
  export class MagicDetector {
12
20
  constructor(context) {
@@ -23,26 +31,18 @@ export class MagicDetector {
23
31
 
24
32
  /**
25
33
  * Audits the project context to map active micro-framework ecosystems.
34
+ * @param {string} baseContextDirectory - Root file workspace context execution vector path
26
35
  */
27
36
  async identifyActiveProjectEcosystems(baseContextDirectory) {
28
37
  await this.ensureInitialized(baseContextDirectory);
29
38
  const activePlugins = await this.registry.getActivePlugins(baseContextDirectory);
30
39
  const activeFrameworkFlags = activePlugins.map(p => p.name);
40
+
41
+ // Universal infrastructure overrides (testing platforms and common bundlers)
31
42
  activeFrameworkFlags.push('universal-tooling-vectors');
32
43
  return activeFrameworkFlags;
33
44
  }
34
45
 
35
- /**
36
- * Version 5.4.0: Delegates entry point detection to the plugin registry.
37
- * @param {string} content - The file content
38
- * @param {string} filePath - The absolute path to the file
39
- * @returns {Array<string>} List of detected entry points
40
- */
41
- async detectEntryPointsFromPlugins(content, filePath) {
42
- await this.ensureInitialized();
43
- return this.registry.detectEntryPointsFromContent(content, filePath);
44
- }
45
-
46
46
  /**
47
47
  * Assesses if a file path acts as an implicit route entry point.
48
48
  */
@@ -60,6 +60,7 @@ export class MagicDetector {
60
60
  }
61
61
  }
62
62
 
63
+ // Apply baseline platform rules (Test suites, lint parameters, continuous integration files)
63
64
  if (this.isCoreToolingSuiteElement(normalizedSystemPath)) {
64
65
  return true;
65
66
  }
@@ -67,46 +68,49 @@ export class MagicDetector {
67
68
  return false;
68
69
  }
69
70
 
70
- /**
71
- * Version 5.3.0: Delegates content analysis to the plugin registry.
72
- */
73
- async runPluginContentAnalysis(node, absolutePath) {
74
- await this.ensureInitialized();
75
- await this.registry.runPluginAnalysis(node, absolutePath);
76
- }
77
-
78
71
  isCoreToolingSuiteElement(normalizedPath) {
72
+ // ── Test / spec files ──────────────────────────────────────────────────────
79
73
  if (/\.(test|spec|e2e|cy)\.(js|ts|tsx|jsx)$/i.test(normalizedPath)) return true;
80
74
  if (/\.stories\.(js|ts|tsx|jsx)$/i.test(normalizedPath)) return true;
81
75
 
76
+ // ── Build / bundler config files ───────────────────────────────────────────
82
77
  const configFragments = [
78
+ // Test runners
83
79
  'jest.config.', 'vitest.config.', 'vitest.workspace.',
84
80
  'playwright.config.', 'cypress.config.',
81
+ // Bundlers
85
82
  'webpack.config.', 'vite.config.', 'rollup.config.',
86
83
  'esbuild.config.', 'parcel.config.',
87
84
  'tsup.config.', 'unbuild.config.', 'pkgroll.config.',
85
+ // CSS / styling
88
86
  'tailwind.config.', 'postcss.config.', '.postcssrc.',
87
+ // Linters / formatters
89
88
  '.eslintrc.', 'eslint.config.', 'prettier.config.', '.prettierrc.',
90
89
  '.stylelintrc.', 'stylelint.config.',
91
90
  'biome.json', '.oxlintrc.',
91
+ // Babel / transpilation
92
92
  '.babelrc.', 'babel.config.',
93
+ // Commit / git hooks
93
94
  '.commitlintrc.', 'commitlint.config.',
94
95
  '.lintstagedrc.', 'lint-staged.config.',
96
+ // Documentation
95
97
  'typedoc.config.', 'typedoc.json',
98
+ // Monorepo tools
96
99
  'turbo.json', 'nx.json', 'lerna.json',
100
+ // Misc tooling
97
101
  'knip.config.', 'knip.json',
98
102
  'syncpack.config.',
103
+ // Internal worker
99
104
  'WorkerTaskRunner.js'
100
105
  ];
101
106
  if (configFragments.some(f => normalizedPath.includes(f))) return true;
102
107
 
108
+ // ── Common application entry points ───────────────────────────────────────
103
109
  const entryPatterns = [
104
110
  // CLI binaries
105
111
  '/bin/cli.js', '/bin/cli.ts', '/bin/cli.mjs',
106
112
  '/bin/index.js', '/bin/index.ts',
107
- // Standard package entry points (poly-extension support)
108
- '/index.js', '/index.ts', '/index.jsx', '/index.tsx', '/index.mjs', '/index.cjs',
109
- // Server / app entry points
113
+ // Server / app entry points (Reduced in v3.3.8 to avoid false positives in libraries)
110
114
  '/src/main.ts', '/src/main.js',
111
115
  '/src/app.ts', '/src/app.js',
112
116
  '/src/api/HeadlessAPI.js', '/src/api/PluginSDK.js',
@@ -115,37 +119,50 @@ export class MagicDetector {
115
119
  ];
116
120
  if (entryPatterns.some(p => normalizedPath.endsWith(p))) return true;
117
121
 
122
+ // ── Next.js App Router conventions ────────────────────────────────────────
123
+ // Files under app/ directory with Next.js special names
118
124
  if (/\/app\/(page|layout|loading|error|not-found|template|default|route|middleware)\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
125
+ // Next.js Pages Router
119
126
  if (/\/pages\/.*\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
127
+ // Next.js API routes
120
128
  if (/\/pages\/api\/.*\.(js|ts)$/.test(normalizedPath)) return true;
129
+ // Next.js middleware
121
130
  if (/\/middleware\.(js|ts)$/.test(normalizedPath)) return true;
131
+ // Next.js config
122
132
  if (/\/next\.config\.(js|ts|mjs|cjs)$/.test(normalizedPath)) return true;
123
133
 
134
+ // ── Remix conventions ─────────────────────────────────────────────────────
124
135
  if (/\/app\/routes\/.*\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
125
136
  if (/\/app\/root\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
126
137
  if (/\/app\/entry\.(client|server)\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
127
138
 
139
+ // ── SvelteKit conventions ─────────────────────────────────────────────────
128
140
  if (/\/\+page(\.(server|client))?\.(svelte|js|ts)$/.test(normalizedPath)) return true;
129
141
  if (/\/\+layout(\.(server|client))?\.(svelte|js|ts)$/.test(normalizedPath)) return true;
130
142
  if (/\/\+error\.(svelte|js|ts)$/.test(normalizedPath)) return true;
131
143
  if (/\/\+server\.(js|ts)$/.test(normalizedPath)) return true;
132
144
  if (/\/svelte\.config\.(js|ts|mjs)$/.test(normalizedPath)) return true;
133
145
 
146
+ // ── Astro conventions ─────────────────────────────────────────────────────
134
147
  if (/\/src\/pages\/.*\.astro$/.test(normalizedPath)) return true;
135
148
  if (/\/src\/layouts\/.*\.astro$/.test(normalizedPath)) return true;
136
149
  if (/\/astro\.config\.(mjs|js|ts)$/.test(normalizedPath)) return true;
137
150
 
151
+ // ── Nuxt conventions ──────────────────────────────────────────────────────
138
152
  if (/\/pages\/.*\.vue$/.test(normalizedPath)) return true;
139
153
  if (/\/layouts\/.*\.vue$/.test(normalizedPath)) return true;
140
154
  if (/\/server\/api\/.*\.(js|ts)$/.test(normalizedPath)) return true;
141
155
  if (/\/nuxt\.config\.(js|ts|mjs)$/.test(normalizedPath)) return true;
142
156
 
157
+ // ── React / Vite entry points ─────────────────────────────────────────────
143
158
  if (/\/vite\.config\.(js|ts|mjs)$/.test(normalizedPath)) return true;
144
159
 
160
+ // ── Angular conventions ───────────────────────────────────────────────────
145
161
  if (/\/main\.(ts|js)$/.test(normalizedPath)) return true;
146
162
  if (/\/app\.module\.(ts|js)$/.test(normalizedPath)) return true;
147
163
  if (/\/angular\.json$/.test(normalizedPath)) return true;
148
164
 
165
+ // ── Expo / React Native ───────────────────────────────────────────────────
149
166
  if (/\/app\/_layout\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
150
167
  if (/\/app\/index\.(js|ts|tsx|jsx)$/.test(normalizedPath)) return true;
151
168
 
@@ -159,8 +176,10 @@ export class MagicDetector {
159
176
  await this.ensureInitialized();
160
177
  if (!await this.isImplicitlyRequiredByEcosystem(filePath, activeFrameworks)) return;
161
178
 
179
+ // Retain entry point elements within memory to keep verification safe
162
180
  fileNode.isEntry = true;
163
181
 
182
+ // Apply dynamic exports coverage metrics based on active platform contracts
164
183
  const normalizedPath = filePath.replace(/\\/g, '/');
165
184
  const plugins = this.registry.getPlugins();
166
185
 
@@ -173,6 +192,7 @@ export class MagicDetector {
173
192
  const contracts = plugin.getRequiredSystemContracts();
174
193
  contracts.forEach(contractMethodToken => {
175
194
  if (fileNode.internalExports.has(contractMethodToken)) {
195
+ // Emulate active local reference linkages to protect the export
176
196
  fileNode.instantiatedIdentifiers.add(contractMethodToken);
177
197
  }
178
198
  });