@nexus-ioc/graph-analyzer 0.1.0 → 0.2.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 +10 -0
- package/README.md +63 -26
- package/dist/analyzer/circular-dependency-detector.d.ts +29 -9
- package/dist/analyzer/circular-dependency-detector.js +106 -63
- package/dist/analyzer/circular-dependency-detector.js.map +1 -1
- package/dist/analyzer/module-depth-analyzer.d.ts +10 -13
- package/dist/analyzer/module-depth-analyzer.js +40 -52
- package/dist/analyzer/module-depth-analyzer.js.map +1 -1
- package/dist/analyzer/provider-scope-analyzer.d.ts +7 -44
- package/dist/analyzer/provider-scope-analyzer.js +13 -84
- package/dist/analyzer/provider-scope-analyzer.js.map +1 -1
- package/dist/analyzer/unused-provider-detector.d.ts +11 -9
- package/dist/analyzer/unused-provider-detector.js +35 -55
- package/dist/analyzer/unused-provider-detector.js.map +1 -1
- package/dist/cli.js +34 -129
- package/dist/cli.js.map +1 -1
- package/dist/config/config-loader.js +3 -27
- package/dist/config/config-loader.js.map +1 -1
- package/dist/config/config-schema.d.ts +2 -16
- package/dist/config/config-schema.js +0 -18
- package/dist/config/config-schema.js.map +1 -1
- package/dist/graph/build-nexus-graph-model.d.ts +13 -0
- package/dist/graph/build-nexus-graph-model.js +202 -0
- package/dist/graph/build-nexus-graph-model.js.map +1 -0
- package/dist/graph/nexus-graph-model.d.ts +112 -0
- package/dist/graph/nexus-graph-model.js +10 -0
- package/dist/graph/nexus-graph-model.js.map +1 -0
- package/dist/graph/scope-resolution.d.ts +16 -0
- package/dist/graph/scope-resolution.js +46 -0
- package/dist/graph/scope-resolution.js.map +1 -0
- package/dist/index.d.ts +27 -29
- package/dist/index.js +34 -34
- package/dist/index.js.map +1 -1
- package/dist/interfaces/graph-output.interface.d.ts +49 -14
- package/dist/utils/error-formatter.js +1 -6
- package/dist/utils/error-formatter.js.map +1 -1
- package/dist/utils/validator.d.ts +0 -5
- package/dist/utils/validator.js +0 -60
- package/dist/utils/validator.js.map +1 -1
- package/dist/visualize/json-formatter.d.ts +5 -6
- package/dist/visualize/json-formatter.js +49 -47
- package/dist/visualize/json-formatter.js.map +1 -1
- package/package.json +5 -4
- package/dist/interfaces/providers.interface.d.ts +0 -10
- package/dist/interfaces/providers.interface.js +0 -3
- package/dist/interfaces/providers.interface.js.map +0 -1
- package/dist/parser/dependency-extractor.d.ts +0 -88
- package/dist/parser/dependency-extractor.js +0 -334
- package/dist/parser/dependency-extractor.js.map +0 -1
- package/dist/parser/parse-entry-file.d.ts +0 -15
- package/dist/parser/parse-entry-file.js +0 -46
- package/dist/parser/parse-entry-file.js.map +0 -1
- package/dist/parser/parse-imports.d.ts +0 -15
- package/dist/parser/parse-imports.js +0 -65
- package/dist/parser/parse-imports.js.map +0 -1
- package/dist/parser/parse-ns-module.d.ts +0 -39
- package/dist/parser/parse-ns-module.js +0 -122
- package/dist/parser/parse-ns-module.js.map +0 -1
- package/dist/parser/parse-provider.d.ts +0 -2
- package/dist/parser/parse-provider.js +0 -7
- package/dist/parser/parse-provider.js.map +0 -1
- package/dist/parser/parse-ts-config.d.ts +0 -10
- package/dist/parser/parse-ts-config.js +0 -40
- package/dist/parser/parse-ts-config.js.map +0 -1
- package/dist/parser/parser-rec.d.ts +0 -1
- package/dist/parser/parser-rec.js +0 -52
- package/dist/parser/parser-rec.js.map +0 -1
- package/dist/parser/parser.d.ts +0 -1
- package/dist/parser/parser.js +0 -61
- package/dist/parser/parser.js.map +0 -1
- package/dist/parser/provider/class-parser.d.ts +0 -20
- package/dist/parser/provider/class-parser.js +0 -137
- package/dist/parser/provider/class-parser.js.map +0 -1
- package/dist/parser/provider/providers-parser.d.ts +0 -9
- package/dist/parser/provider/providers-parser.js +0 -32
- package/dist/parser/provider/providers-parser.js.map +0 -1
- package/dist/parser/provider/use-class-parser.d.ts +0 -25
- package/dist/parser/provider/use-class-parser.js +0 -161
- package/dist/parser/provider/use-class-parser.js.map +0 -1
- package/dist/parser/provider/use-factory-parser.d.ts +0 -15
- package/dist/parser/provider/use-factory-parser.js +0 -53
- package/dist/parser/provider/use-factory-parser.js.map +0 -1
- package/dist/parser/provider/use-value-parser.d.ts +0 -13
- package/dist/parser/provider/use-value-parser.js +0 -41
- package/dist/parser/provider/use-value-parser.js.map +0 -1
- package/dist/parser/rules.d.ts +0 -10
- package/dist/parser/rules.js +0 -37
- package/dist/parser/rules.js.map +0 -1
- package/dist/visualize/generator.d.ts +0 -26
- package/dist/visualize/generator.js +0 -75
- package/dist/visualize/generator.js.map +0 -1
- package/dist/visualize/graph-analyzer.d.ts +0 -126
- package/dist/visualize/graph-analyzer.js +0 -199
- package/dist/visualize/graph-analyzer.js.map +0 -1
- package/dist/visualize/html-generator.d.ts +0 -71
- package/dist/visualize/html-generator.js +0 -1312
- package/dist/visualize/html-generator.js.map +0 -1
|
@@ -11,7 +11,7 @@ exports.ModuleDepthAnalyzer = void 0;
|
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```typescript
|
|
14
|
-
* const analyzer = new ModuleDepthAnalyzer(
|
|
14
|
+
* const analyzer = new ModuleDepthAnalyzer(graphModel);
|
|
15
15
|
* const analysis = analyzer.analyze();
|
|
16
16
|
*
|
|
17
17
|
* console.log(`Max depth: ${analysis.maxDepth}`);
|
|
@@ -26,11 +26,11 @@ class ModuleDepthAnalyzer {
|
|
|
26
26
|
/**
|
|
27
27
|
* Create a new ModuleDepthAnalyzer instance
|
|
28
28
|
*
|
|
29
|
-
* @param
|
|
29
|
+
* @param graphModel - The application's graph model
|
|
30
30
|
* @param deepModuleThreshold - Custom threshold for deep modules (optional)
|
|
31
31
|
*/
|
|
32
|
-
constructor(
|
|
33
|
-
this.
|
|
32
|
+
constructor(graphModel, deepModuleThreshold = 5) {
|
|
33
|
+
this.graphModel = graphModel;
|
|
34
34
|
this.deepModuleThreshold = deepModuleThreshold;
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
@@ -39,12 +39,14 @@ class ModuleDepthAnalyzer {
|
|
|
39
39
|
* @returns ModuleDepthAnalysis with all calculated metrics
|
|
40
40
|
*/
|
|
41
41
|
analyze() {
|
|
42
|
-
|
|
43
|
-
if (modules.length === 0) {
|
|
42
|
+
if (this.graphModel.modules.size === 0) {
|
|
44
43
|
return this.createEmptyAnalysis();
|
|
45
44
|
}
|
|
46
45
|
// Calculate depth for each module
|
|
47
46
|
const moduleDepths = this.calculateModuleDepths();
|
|
47
|
+
if (moduleDepths.size === 0) {
|
|
48
|
+
return this.createEmptyAnalysis();
|
|
49
|
+
}
|
|
48
50
|
// Calculate complexity metrics
|
|
49
51
|
const moduleDetails = this.calculateComplexityMetrics(moduleDepths);
|
|
50
52
|
// Group modules by depth level
|
|
@@ -66,69 +68,58 @@ class ModuleDepthAnalyzer {
|
|
|
66
68
|
};
|
|
67
69
|
}
|
|
68
70
|
/**
|
|
69
|
-
*
|
|
70
|
-
*/
|
|
71
|
-
getModules() {
|
|
72
|
-
const modules = [];
|
|
73
|
-
for (const [key, value] of this.graph.entries()) {
|
|
74
|
-
if (key !== "entry" && "imports" in value) {
|
|
75
|
-
modules.push(value);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return modules;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Calculate depth for each module using BFS from entry point
|
|
71
|
+
* Calculate depth for each module (by id) using BFS from entry point
|
|
82
72
|
*/
|
|
83
73
|
calculateModuleDepths() {
|
|
84
74
|
const depths = new Map();
|
|
85
|
-
const
|
|
86
|
-
if (!
|
|
75
|
+
const entryModuleId = this.graphModel.entryModuleId;
|
|
76
|
+
if (!entryModuleId || !this.graphModel.modules.has(entryModuleId)) {
|
|
87
77
|
return depths;
|
|
88
78
|
}
|
|
89
79
|
// Start BFS from entry module
|
|
90
80
|
const queue = [
|
|
91
|
-
{
|
|
81
|
+
{ id: entryModuleId, depth: 0 },
|
|
92
82
|
];
|
|
93
83
|
const visited = new Set();
|
|
94
84
|
while (queue.length > 0) {
|
|
95
85
|
const current = queue.shift();
|
|
96
|
-
if (visited.has(current.
|
|
86
|
+
if (visited.has(current.id)) {
|
|
97
87
|
continue;
|
|
98
88
|
}
|
|
99
|
-
visited.add(current.
|
|
100
|
-
depths.set(current.
|
|
89
|
+
visited.add(current.id);
|
|
90
|
+
depths.set(current.id, current.depth);
|
|
101
91
|
// Get module from graph
|
|
102
|
-
const module = this.
|
|
103
|
-
if (!module
|
|
92
|
+
const module = this.graphModel.modules.get(current.id);
|
|
93
|
+
if (!module) {
|
|
104
94
|
continue;
|
|
105
95
|
}
|
|
106
96
|
// Add all imports to queue with incremented depth
|
|
107
|
-
for (const
|
|
108
|
-
if (!visited.has(
|
|
109
|
-
queue.push({
|
|
97
|
+
for (const importedModule of module.imports) {
|
|
98
|
+
if (!visited.has(importedModule.id)) {
|
|
99
|
+
queue.push({ id: importedModule.id, depth: current.depth + 1 });
|
|
110
100
|
}
|
|
111
101
|
}
|
|
112
102
|
}
|
|
113
103
|
return depths;
|
|
114
104
|
}
|
|
115
105
|
/**
|
|
116
|
-
* Calculate complexity metrics for each module
|
|
106
|
+
* Calculate complexity metrics for each module. `moduleDepths` is keyed
|
|
107
|
+
* by id; the returned `ModuleDepthInfo[]` reports display names, as before.
|
|
117
108
|
*/
|
|
118
109
|
calculateComplexityMetrics(moduleDepths) {
|
|
119
110
|
const moduleDetails = [];
|
|
120
111
|
const fanInMap = this.calculateFanIn();
|
|
121
|
-
for (const [
|
|
122
|
-
const module = this.
|
|
123
|
-
if (!module
|
|
112
|
+
for (const [moduleId, depth] of moduleDepths.entries()) {
|
|
113
|
+
const module = this.graphModel.modules.get(moduleId);
|
|
114
|
+
if (!module) {
|
|
124
115
|
continue;
|
|
125
116
|
}
|
|
126
117
|
const directImports = module.imports.length;
|
|
127
|
-
const transitiveDependencies = this.calculateTransitiveDependencies(
|
|
128
|
-
const fanIn = fanInMap.get(
|
|
118
|
+
const transitiveDependencies = this.calculateTransitiveDependencies(moduleId);
|
|
119
|
+
const fanIn = fanInMap.get(moduleId) || 0;
|
|
129
120
|
const fanOut = directImports;
|
|
130
121
|
moduleDetails.push({
|
|
131
|
-
name:
|
|
122
|
+
name: module.name,
|
|
132
123
|
depth,
|
|
133
124
|
directImports,
|
|
134
125
|
transitiveDependencies,
|
|
@@ -139,17 +130,14 @@ class ModuleDepthAnalyzer {
|
|
|
139
130
|
return moduleDetails;
|
|
140
131
|
}
|
|
141
132
|
/**
|
|
142
|
-
* Calculate fan-in for all modules (how many modules depend on each
|
|
133
|
+
* Calculate fan-in for all modules (how many modules depend on each
|
|
134
|
+
* module), keyed by id
|
|
143
135
|
*/
|
|
144
136
|
calculateFanIn() {
|
|
145
137
|
const fanInMap = new Map();
|
|
146
|
-
for (const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
const module = value;
|
|
151
|
-
for (const importName of module.imports) {
|
|
152
|
-
fanInMap.set(importName, (fanInMap.get(importName) || 0) + 1);
|
|
138
|
+
for (const module of this.graphModel.modules.values()) {
|
|
139
|
+
for (const importedModule of module.imports) {
|
|
140
|
+
fanInMap.set(importedModule.id, (fanInMap.get(importedModule.id) || 0) + 1);
|
|
153
141
|
}
|
|
154
142
|
}
|
|
155
143
|
return fanInMap;
|
|
@@ -157,22 +145,22 @@ class ModuleDepthAnalyzer {
|
|
|
157
145
|
/**
|
|
158
146
|
* Calculate transitive dependencies for a module (all modules it depends on)
|
|
159
147
|
*/
|
|
160
|
-
calculateTransitiveDependencies(
|
|
148
|
+
calculateTransitiveDependencies(moduleId) {
|
|
161
149
|
const visited = new Set();
|
|
162
|
-
const queue = [
|
|
150
|
+
const queue = [moduleId];
|
|
163
151
|
while (queue.length > 0) {
|
|
164
152
|
const current = queue.shift();
|
|
165
153
|
if (visited.has(current)) {
|
|
166
154
|
continue;
|
|
167
155
|
}
|
|
168
156
|
visited.add(current);
|
|
169
|
-
const module = this.
|
|
170
|
-
if (!module
|
|
157
|
+
const module = this.graphModel.modules.get(current);
|
|
158
|
+
if (!module) {
|
|
171
159
|
continue;
|
|
172
160
|
}
|
|
173
|
-
for (const
|
|
174
|
-
if (!visited.has(
|
|
175
|
-
queue.push(
|
|
161
|
+
for (const importedModule of module.imports) {
|
|
162
|
+
if (!visited.has(importedModule.id)) {
|
|
163
|
+
queue.push(importedModule.id);
|
|
176
164
|
}
|
|
177
165
|
}
|
|
178
166
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-depth-analyzer.js","sourceRoot":"","sources":["../../src/analyzer/module-depth-analyzer.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"module-depth-analyzer.js","sourceRoot":"","sources":["../../src/analyzer/module-depth-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ParseNsModule } from "../parser/parse-ns-module";
|
|
1
|
+
import type { NexusGraphModel } from "../graph/nexus-graph-model";
|
|
3
2
|
/**
|
|
4
3
|
* Provider scope types
|
|
5
4
|
*/
|
|
6
|
-
export type ProviderScope = "Singleton" | "
|
|
5
|
+
export type ProviderScope = "Singleton" | "Transient";
|
|
7
6
|
/**
|
|
8
7
|
* Information about a provider's scope
|
|
9
8
|
*/
|
|
@@ -19,27 +18,6 @@ export interface ProviderScopeInfo {
|
|
|
19
18
|
/** Dependencies of this provider */
|
|
20
19
|
dependencies: string[];
|
|
21
20
|
}
|
|
22
|
-
/**
|
|
23
|
-
* Scope mismatch issue
|
|
24
|
-
*/
|
|
25
|
-
export interface ScopeMismatch {
|
|
26
|
-
/** Provider with scope issue */
|
|
27
|
-
provider: string;
|
|
28
|
-
/** Provider's scope */
|
|
29
|
-
providerScope: ProviderScope;
|
|
30
|
-
/** Module that registers the provider */
|
|
31
|
-
module: string;
|
|
32
|
-
/** Dependency that causes the mismatch */
|
|
33
|
-
dependency: string;
|
|
34
|
-
/** Dependency's scope */
|
|
35
|
-
dependencyScope: ProviderScope;
|
|
36
|
-
/** Severity of the issue */
|
|
37
|
-
severity: "error" | "warning";
|
|
38
|
-
/** Description of the issue */
|
|
39
|
-
message: string;
|
|
40
|
-
/** Suggestions for fixing the issue */
|
|
41
|
-
suggestions: string[];
|
|
42
|
-
}
|
|
43
21
|
/**
|
|
44
22
|
* Provider scope analysis results
|
|
45
23
|
*/
|
|
@@ -50,24 +28,17 @@ export interface ProviderScopeAnalysis {
|
|
|
50
28
|
totalProviders: number;
|
|
51
29
|
/** Number of singleton providers */
|
|
52
30
|
singletonProviders: number;
|
|
53
|
-
/** Number of
|
|
54
|
-
|
|
55
|
-
/** Scope mismatches detected */
|
|
56
|
-
scopeMismatches: ScopeMismatch[];
|
|
31
|
+
/** Number of transient providers */
|
|
32
|
+
transientProviders: number;
|
|
57
33
|
/** All provider scope information */
|
|
58
34
|
providerScopes: ProviderScopeInfo[];
|
|
59
35
|
}
|
|
60
36
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* This analyzer identifies:
|
|
64
|
-
* - Singleton providers depending on request-scoped providers (scope mismatch)
|
|
65
|
-
* - Potential memory leaks from scope misuse
|
|
66
|
-
* - Scope optimization opportunities
|
|
37
|
+
* Reports each provider's scope (Singleton or Transient).
|
|
67
38
|
*/
|
|
68
39
|
export declare class ProviderScopeAnalyzer {
|
|
69
|
-
private readonly
|
|
70
|
-
constructor(
|
|
40
|
+
private readonly graphModel;
|
|
41
|
+
constructor(graphModel: NexusGraphModel);
|
|
71
42
|
/**
|
|
72
43
|
* Analyze provider scopes and detect issues
|
|
73
44
|
*/
|
|
@@ -80,12 +51,4 @@ export declare class ProviderScopeAnalyzer {
|
|
|
80
51
|
* Extract scope from provider
|
|
81
52
|
*/
|
|
82
53
|
private extractProviderScope;
|
|
83
|
-
/**
|
|
84
|
-
* Extract dependency tokens from provider
|
|
85
|
-
*/
|
|
86
|
-
private extractDependencyTokens;
|
|
87
|
-
/**
|
|
88
|
-
* Detect scope mismatches in provider dependencies
|
|
89
|
-
*/
|
|
90
|
-
private detectScopeMismatches;
|
|
91
54
|
}
|
|
@@ -2,16 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ProviderScopeAnalyzer = void 0;
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* This analyzer identifies:
|
|
8
|
-
* - Singleton providers depending on request-scoped providers (scope mismatch)
|
|
9
|
-
* - Potential memory leaks from scope misuse
|
|
10
|
-
* - Scope optimization opportunities
|
|
5
|
+
* Reports each provider's scope (Singleton or Transient).
|
|
11
6
|
*/
|
|
12
7
|
class ProviderScopeAnalyzer {
|
|
13
|
-
constructor(
|
|
14
|
-
this.
|
|
8
|
+
constructor(graphModel) {
|
|
9
|
+
this.graphModel = graphModel;
|
|
15
10
|
}
|
|
16
11
|
/**
|
|
17
12
|
* Analyze provider scopes and detect issues
|
|
@@ -19,17 +14,14 @@ class ProviderScopeAnalyzer {
|
|
|
19
14
|
analyze() {
|
|
20
15
|
// Build provider scope map
|
|
21
16
|
const providerScopes = this.buildProviderScopeMap();
|
|
22
|
-
// Detect scope mismatches
|
|
23
|
-
const scopeMismatches = this.detectScopeMismatches(providerScopes);
|
|
24
17
|
// Calculate statistics
|
|
25
18
|
const singletonCount = providerScopes.filter((p) => p.scope === "Singleton").length;
|
|
26
|
-
const
|
|
19
|
+
const transientCount = providerScopes.filter((p) => p.scope === "Transient").length;
|
|
27
20
|
return {
|
|
28
21
|
hasScopeAnalysis: true,
|
|
29
22
|
totalProviders: providerScopes.length,
|
|
30
23
|
singletonProviders: singletonCount,
|
|
31
|
-
|
|
32
|
-
scopeMismatches,
|
|
24
|
+
transientProviders: transientCount,
|
|
33
25
|
providerScopes,
|
|
34
26
|
};
|
|
35
27
|
}
|
|
@@ -38,20 +30,15 @@ class ProviderScopeAnalyzer {
|
|
|
38
30
|
*/
|
|
39
31
|
buildProviderScopeMap() {
|
|
40
32
|
const providerScopes = [];
|
|
41
|
-
for (const
|
|
42
|
-
|
|
43
|
-
continue;
|
|
44
|
-
const parseNsModule = value;
|
|
45
|
-
if (!parseNsModule.providers)
|
|
46
|
-
continue;
|
|
47
|
-
for (const provider of parseNsModule.providers) {
|
|
48
|
-
if (!provider.token)
|
|
49
|
-
continue;
|
|
33
|
+
for (const module of this.graphModel.modules.values()) {
|
|
34
|
+
for (const provider of module.providers) {
|
|
50
35
|
const scope = this.extractProviderScope(provider);
|
|
51
|
-
const dependencies =
|
|
36
|
+
const dependencies = provider.dependencies
|
|
37
|
+
.filter((dep) => !dep.optional)
|
|
38
|
+
.map((dep) => dep.token);
|
|
52
39
|
providerScopes.push({
|
|
53
40
|
token: provider.token,
|
|
54
|
-
module:
|
|
41
|
+
module: module.name,
|
|
55
42
|
scope,
|
|
56
43
|
type: provider.type,
|
|
57
44
|
dependencies,
|
|
@@ -67,71 +54,13 @@ class ProviderScopeAnalyzer {
|
|
|
67
54
|
// Check if scope is explicitly defined (applies to all provider types)
|
|
68
55
|
if (provider.scope) {
|
|
69
56
|
const scopeStr = provider.scope.toLowerCase();
|
|
70
|
-
if (scopeStr.includes("
|
|
71
|
-
return "
|
|
57
|
+
if (scopeStr.includes("transient") || scopeStr === "2") {
|
|
58
|
+
return "Transient";
|
|
72
59
|
}
|
|
73
60
|
}
|
|
74
61
|
// Default to Singleton for all provider types
|
|
75
62
|
return "Singleton";
|
|
76
63
|
}
|
|
77
|
-
/**
|
|
78
|
-
* Extract dependency tokens from provider
|
|
79
|
-
*/
|
|
80
|
-
extractDependencyTokens(provider) {
|
|
81
|
-
const tokens = [];
|
|
82
|
-
// Extract from dependencies array (Class and UseClass providers)
|
|
83
|
-
if (provider.dependencies && Array.isArray(provider.dependencies)) {
|
|
84
|
-
for (const dep of provider.dependencies) {
|
|
85
|
-
if (dep.token && !dep.optional) {
|
|
86
|
-
tokens.push(dep.token);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
// Extract from inject array (UseFactory providers)
|
|
91
|
-
if (provider.inject && Array.isArray(provider.inject)) {
|
|
92
|
-
tokens.push(...provider.inject);
|
|
93
|
-
}
|
|
94
|
-
return tokens;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Detect scope mismatches in provider dependencies
|
|
98
|
-
*/
|
|
99
|
-
detectScopeMismatches(providerScopes) {
|
|
100
|
-
const mismatches = [];
|
|
101
|
-
const scopeMap = new Map();
|
|
102
|
-
// Build lookup map
|
|
103
|
-
for (const provider of providerScopes) {
|
|
104
|
-
scopeMap.set(provider.token, provider);
|
|
105
|
-
}
|
|
106
|
-
// Check each provider's dependencies
|
|
107
|
-
for (const provider of providerScopes) {
|
|
108
|
-
// Only check Singleton providers (they shouldn't depend on Request-scoped)
|
|
109
|
-
if (provider.scope !== "Singleton") {
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
for (const depToken of provider.dependencies) {
|
|
113
|
-
const dependency = scopeMap.get(depToken);
|
|
114
|
-
// If dependency is Request-scoped, this is a scope mismatch
|
|
115
|
-
if (dependency && dependency.scope === "Request") {
|
|
116
|
-
mismatches.push({
|
|
117
|
-
provider: provider.token,
|
|
118
|
-
providerScope: provider.scope,
|
|
119
|
-
module: provider.module,
|
|
120
|
-
dependency: depToken,
|
|
121
|
-
dependencyScope: dependency.scope,
|
|
122
|
-
severity: "error",
|
|
123
|
-
message: `Singleton provider '${provider.token}' depends on Request-scoped provider '${depToken}'. This can cause memory leaks and unexpected behavior.`,
|
|
124
|
-
suggestions: [
|
|
125
|
-
`Change '${provider.token}' to Request scope`,
|
|
126
|
-
`Change '${depToken}' to Singleton scope if it doesn't need request-specific state`,
|
|
127
|
-
"Use a factory or lazy injection to resolve the dependency per request",
|
|
128
|
-
],
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return mismatches;
|
|
134
|
-
}
|
|
135
64
|
}
|
|
136
65
|
exports.ProviderScopeAnalyzer = ProviderScopeAnalyzer;
|
|
137
66
|
//# sourceMappingURL=provider-scope-analyzer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-scope-analyzer.js","sourceRoot":"","sources":["../../src/analyzer/provider-scope-analyzer.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"provider-scope-analyzer.js","sourceRoot":"","sources":["../../src/analyzer/provider-scope-analyzer.ts"],"names":[],"mappings":";;;AA0CA;;GAEG;AACH,MAAa,qBAAqB;IACjC,YAA6B,UAA2B;QAA3B,eAAU,GAAV,UAAU,CAAiB;IAAG,CAAC;IAE5D;;OAEG;IACH,OAAO;QACN,2BAA2B;QAC3B,MAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAEpD,uBAAuB;QACvB,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,CAC3C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,WAAW,CAC9B,CAAC,MAAM,CAAC;QACT,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,CAC3C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,WAAW,CAC9B,CAAC,MAAM,CAAC;QAET,OAAO;YACN,gBAAgB,EAAE,IAAI;YACtB,cAAc,EAAE,cAAc,CAAC,MAAM;YACrC,kBAAkB,EAAE,cAAc;YAClC,kBAAkB,EAAE,cAAc;YAClC,cAAc;SACd,CAAC;IACH,CAAC;IAED;;OAEG;IACK,qBAAqB;QAC5B,MAAM,cAAc,GAAwB,EAAE,CAAC;QAE/C,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YACvD,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBACzC,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;gBAClD,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY;qBACxC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC;qBAC9B,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAE1B,cAAc,CAAC,IAAI,CAAC;oBACnB,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,MAAM,EAAE,MAAM,CAAC,IAAI;oBACnB,KAAK;oBACL,IAAI,EAAE,QAAQ,CAAC,IAAI;oBACnB,YAAY;iBACZ,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;QAED,OAAO,cAAc,CAAC;IACvB,CAAC;IAED;;OAEG;IACK,oBAAoB,CAAC,QAA2B;QACvD,uEAAuE;QACvE,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YACpB,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YAC9C,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;gBACxD,OAAO,WAAW,CAAC;YACpB,CAAC;QACF,CAAC;QAED,8CAA8C;QAC9C,OAAO,WAAW,CAAC;IACpB,CAAC;CACD;AApED,sDAoEC"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ParseNsModule } from "../parser/parse-ns-module";
|
|
1
|
+
import type { NexusGraphModel } from "../graph/nexus-graph-model";
|
|
3
2
|
/**
|
|
4
3
|
* Information about an unused provider
|
|
5
4
|
*/
|
|
@@ -38,7 +37,7 @@ export interface UnusedProviderAnalysis {
|
|
|
38
37
|
*
|
|
39
38
|
* @example
|
|
40
39
|
* ```typescript
|
|
41
|
-
* const detector = new UnusedProviderDetector(
|
|
40
|
+
* const detector = new UnusedProviderDetector(graphModel);
|
|
42
41
|
* const analysis = detector.analyze();
|
|
43
42
|
*
|
|
44
43
|
* if (analysis.hasUnusedProviders) {
|
|
@@ -50,8 +49,8 @@ export interface UnusedProviderAnalysis {
|
|
|
50
49
|
* ```
|
|
51
50
|
*/
|
|
52
51
|
export declare class UnusedProviderDetector {
|
|
53
|
-
private readonly
|
|
54
|
-
constructor(
|
|
52
|
+
private readonly graphModel;
|
|
53
|
+
constructor(graphModel: NexusGraphModel);
|
|
55
54
|
/**
|
|
56
55
|
* Analyze the graph for unused providers
|
|
57
56
|
*
|
|
@@ -59,13 +58,16 @@ export declare class UnusedProviderDetector {
|
|
|
59
58
|
*/
|
|
60
59
|
analyze(): UnusedProviderAnalysis;
|
|
61
60
|
/**
|
|
62
|
-
* Build a set of all provider
|
|
61
|
+
* Build a set of all provider ids that are injected as dependencies.
|
|
62
|
+
* Keyed by `GraphProviderDependency.tokenId` (collision-free), not the
|
|
63
|
+
* rendered `token` — two different provider classes named alike must
|
|
64
|
+
* not collapse into one set entry.
|
|
63
65
|
*/
|
|
64
|
-
private
|
|
66
|
+
private buildInjectedIdsSet;
|
|
65
67
|
/**
|
|
66
|
-
* Build a set of all provider
|
|
68
|
+
* Build a set of all provider/module ids that are exported from modules
|
|
67
69
|
*/
|
|
68
|
-
private
|
|
70
|
+
private buildExportedIdsSet;
|
|
69
71
|
/**
|
|
70
72
|
* Generate suggestions for resolving an unused provider
|
|
71
73
|
*/
|
|
@@ -11,7 +11,7 @@ exports.UnusedProviderDetector = void 0;
|
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```typescript
|
|
14
|
-
* const detector = new UnusedProviderDetector(
|
|
14
|
+
* const detector = new UnusedProviderDetector(graphModel);
|
|
15
15
|
* const analysis = detector.analyze();
|
|
16
16
|
*
|
|
17
17
|
* if (analysis.hasUnusedProviders) {
|
|
@@ -23,8 +23,8 @@ exports.UnusedProviderDetector = void 0;
|
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
25
|
class UnusedProviderDetector {
|
|
26
|
-
constructor(
|
|
27
|
-
this.
|
|
26
|
+
constructor(graphModel) {
|
|
27
|
+
this.graphModel = graphModel;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* Analyze the graph for unused providers
|
|
@@ -33,42 +33,33 @@ class UnusedProviderDetector {
|
|
|
33
33
|
*/
|
|
34
34
|
analyze() {
|
|
35
35
|
const unusedProviders = [];
|
|
36
|
-
// Build a set of all injected provider
|
|
37
|
-
const
|
|
38
|
-
// Build a set of all exported provider
|
|
39
|
-
const
|
|
36
|
+
// Build a set of all injected provider ids
|
|
37
|
+
const injectedIds = this.buildInjectedIdsSet();
|
|
38
|
+
// Build a set of all exported provider/module ids
|
|
39
|
+
const exportedIds = this.buildExportedIdsSet();
|
|
40
40
|
// Check each module for unused providers
|
|
41
|
-
for (const
|
|
42
|
-
if (moduleName === "entry")
|
|
43
|
-
continue;
|
|
44
|
-
const nsModule = module;
|
|
45
|
-
if (!nsModule.providers || nsModule.providers.length === 0)
|
|
46
|
-
continue;
|
|
41
|
+
for (const module of this.graphModel.modules.values()) {
|
|
47
42
|
// Check each provider in the module
|
|
48
|
-
for (const provider of
|
|
43
|
+
for (const provider of module.providers) {
|
|
49
44
|
const token = provider.token;
|
|
50
|
-
// Skip providers with null tokens
|
|
51
|
-
if (!token)
|
|
52
|
-
continue;
|
|
53
45
|
// Skip if the provider is injected somewhere
|
|
54
|
-
if (
|
|
46
|
+
if (injectedIds.has(provider.id))
|
|
55
47
|
continue;
|
|
56
48
|
// Skip if the provider is exported (it may be used externally)
|
|
57
|
-
|
|
49
|
+
const isExported = exportedIds.has(provider.id);
|
|
50
|
+
if (isExported)
|
|
58
51
|
continue;
|
|
59
52
|
// Skip if the module is global (providers may be used across the app)
|
|
60
|
-
if (
|
|
53
|
+
if (module.isGlobal)
|
|
61
54
|
continue;
|
|
62
55
|
// This provider is unused
|
|
63
|
-
const suggestions = this.generateSuggestions(token,
|
|
64
|
-
// Normalize provider type to match expected union type
|
|
65
|
-
const providerType = provider.type;
|
|
56
|
+
const suggestions = this.generateSuggestions(token, module.name, isExported, module.isGlobal);
|
|
66
57
|
unusedProviders.push({
|
|
67
58
|
token,
|
|
68
|
-
module:
|
|
69
|
-
type:
|
|
59
|
+
module: module.name,
|
|
60
|
+
type: provider.type,
|
|
70
61
|
severity: "warning",
|
|
71
|
-
message: `Provider '${token}' is registered in '${
|
|
62
|
+
message: `Provider '${token}' is registered in '${module.name}' but never injected`,
|
|
72
63
|
suggestions,
|
|
73
64
|
});
|
|
74
65
|
}
|
|
@@ -80,47 +71,36 @@ class UnusedProviderDetector {
|
|
|
80
71
|
};
|
|
81
72
|
}
|
|
82
73
|
/**
|
|
83
|
-
* Build a set of all provider
|
|
74
|
+
* Build a set of all provider ids that are injected as dependencies.
|
|
75
|
+
* Keyed by `GraphProviderDependency.tokenId` (collision-free), not the
|
|
76
|
+
* rendered `token` — two different provider classes named alike must
|
|
77
|
+
* not collapse into one set entry.
|
|
84
78
|
*/
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
for (const
|
|
88
|
-
|
|
89
|
-
continue;
|
|
90
|
-
const nsModule = module;
|
|
91
|
-
if (!nsModule.providers)
|
|
92
|
-
continue;
|
|
93
|
-
// Check dependencies of each provider
|
|
94
|
-
for (const provider of nsModule.providers) {
|
|
95
|
-
if (!provider.dependencies)
|
|
96
|
-
continue;
|
|
79
|
+
buildInjectedIdsSet() {
|
|
80
|
+
const injectedIds = new Set();
|
|
81
|
+
for (const module of this.graphModel.modules.values()) {
|
|
82
|
+
for (const provider of module.providers) {
|
|
97
83
|
for (const dependency of provider.dependencies) {
|
|
98
84
|
// Skip optional dependencies as they may not be required
|
|
99
|
-
if (!dependency.optional) {
|
|
100
|
-
|
|
85
|
+
if (!dependency.optional && dependency.tokenId) {
|
|
86
|
+
injectedIds.add(dependency.tokenId);
|
|
101
87
|
}
|
|
102
88
|
}
|
|
103
89
|
}
|
|
104
90
|
}
|
|
105
|
-
return
|
|
91
|
+
return injectedIds;
|
|
106
92
|
}
|
|
107
93
|
/**
|
|
108
|
-
* Build a set of all provider
|
|
94
|
+
* Build a set of all provider/module ids that are exported from modules
|
|
109
95
|
*/
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
for (const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const nsModule = module;
|
|
116
|
-
if (!nsModule.exports)
|
|
117
|
-
continue;
|
|
118
|
-
// Add all exported tokens
|
|
119
|
-
for (const exportedToken of nsModule.exports) {
|
|
120
|
-
exportedTokens.add(exportedToken);
|
|
96
|
+
buildExportedIdsSet() {
|
|
97
|
+
const exportedIds = new Set();
|
|
98
|
+
for (const module of this.graphModel.modules.values()) {
|
|
99
|
+
for (const exportedEntry of module.exports) {
|
|
100
|
+
exportedIds.add(exportedEntry.id);
|
|
121
101
|
}
|
|
122
102
|
}
|
|
123
|
-
return
|
|
103
|
+
return exportedIds;
|
|
124
104
|
}
|
|
125
105
|
/**
|
|
126
106
|
* Generate suggestions for resolving an unused provider
|