@nexus-ioc/graph-analyzer 0.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.
Files changed (98) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/LICENSE +21 -0
  3. package/README.md +742 -0
  4. package/dist/analyzer/circular-dependency-detector.d.ts +94 -0
  5. package/dist/analyzer/circular-dependency-detector.js +203 -0
  6. package/dist/analyzer/circular-dependency-detector.js.map +1 -0
  7. package/dist/analyzer/module-depth-analyzer.d.ts +117 -0
  8. package/dist/analyzer/module-depth-analyzer.js +221 -0
  9. package/dist/analyzer/module-depth-analyzer.js.map +1 -0
  10. package/dist/analyzer/provider-scope-analyzer.d.ts +91 -0
  11. package/dist/analyzer/provider-scope-analyzer.js +137 -0
  12. package/dist/analyzer/provider-scope-analyzer.js.map +1 -0
  13. package/dist/analyzer/unused-provider-detector.d.ts +73 -0
  14. package/dist/analyzer/unused-provider-detector.js +147 -0
  15. package/dist/analyzer/unused-provider-detector.js.map +1 -0
  16. package/dist/cli.d.ts +2 -0
  17. package/dist/cli.js +537 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/config/config-loader.d.ts +27 -0
  20. package/dist/config/config-loader.js +205 -0
  21. package/dist/config/config-loader.js.map +1 -0
  22. package/dist/config/config-schema.d.ts +83 -0
  23. package/dist/config/config-schema.js +97 -0
  24. package/dist/config/config-schema.js.map +1 -0
  25. package/dist/index.d.ts +41 -0
  26. package/dist/index.js +50 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/interfaces/graph-output.interface.d.ts +126 -0
  29. package/dist/interfaces/graph-output.interface.js +3 -0
  30. package/dist/interfaces/graph-output.interface.js.map +1 -0
  31. package/dist/interfaces/providers.interface.d.ts +10 -0
  32. package/dist/interfaces/providers.interface.js +3 -0
  33. package/dist/interfaces/providers.interface.js.map +1 -0
  34. package/dist/parser/dependency-extractor.d.ts +88 -0
  35. package/dist/parser/dependency-extractor.js +334 -0
  36. package/dist/parser/dependency-extractor.js.map +1 -0
  37. package/dist/parser/parse-entry-file.d.ts +15 -0
  38. package/dist/parser/parse-entry-file.js +46 -0
  39. package/dist/parser/parse-entry-file.js.map +1 -0
  40. package/dist/parser/parse-imports.d.ts +15 -0
  41. package/dist/parser/parse-imports.js +65 -0
  42. package/dist/parser/parse-imports.js.map +1 -0
  43. package/dist/parser/parse-ns-module.d.ts +39 -0
  44. package/dist/parser/parse-ns-module.js +122 -0
  45. package/dist/parser/parse-ns-module.js.map +1 -0
  46. package/dist/parser/parse-provider.d.ts +2 -0
  47. package/dist/parser/parse-provider.js +7 -0
  48. package/dist/parser/parse-provider.js.map +1 -0
  49. package/dist/parser/parse-ts-config.d.ts +10 -0
  50. package/dist/parser/parse-ts-config.js +40 -0
  51. package/dist/parser/parse-ts-config.js.map +1 -0
  52. package/dist/parser/parser-rec.d.ts +1 -0
  53. package/dist/parser/parser-rec.js +52 -0
  54. package/dist/parser/parser-rec.js.map +1 -0
  55. package/dist/parser/parser.d.ts +1 -0
  56. package/dist/parser/parser.js +61 -0
  57. package/dist/parser/parser.js.map +1 -0
  58. package/dist/parser/provider/class-parser.d.ts +20 -0
  59. package/dist/parser/provider/class-parser.js +137 -0
  60. package/dist/parser/provider/class-parser.js.map +1 -0
  61. package/dist/parser/provider/providers-parser.d.ts +9 -0
  62. package/dist/parser/provider/providers-parser.js +32 -0
  63. package/dist/parser/provider/providers-parser.js.map +1 -0
  64. package/dist/parser/provider/use-class-parser.d.ts +25 -0
  65. package/dist/parser/provider/use-class-parser.js +161 -0
  66. package/dist/parser/provider/use-class-parser.js.map +1 -0
  67. package/dist/parser/provider/use-factory-parser.d.ts +15 -0
  68. package/dist/parser/provider/use-factory-parser.js +53 -0
  69. package/dist/parser/provider/use-factory-parser.js.map +1 -0
  70. package/dist/parser/provider/use-value-parser.d.ts +13 -0
  71. package/dist/parser/provider/use-value-parser.js +41 -0
  72. package/dist/parser/provider/use-value-parser.js.map +1 -0
  73. package/dist/parser/rules.d.ts +10 -0
  74. package/dist/parser/rules.js +37 -0
  75. package/dist/parser/rules.js.map +1 -0
  76. package/dist/utils/error-formatter.d.ts +27 -0
  77. package/dist/utils/error-formatter.js +177 -0
  78. package/dist/utils/error-formatter.js.map +1 -0
  79. package/dist/utils/validator.d.ts +45 -0
  80. package/dist/utils/validator.js +252 -0
  81. package/dist/utils/validator.js.map +1 -0
  82. package/dist/visualize/generator.d.ts +26 -0
  83. package/dist/visualize/generator.js +75 -0
  84. package/dist/visualize/generator.js.map +1 -0
  85. package/dist/visualize/graph-analyzer.d.ts +126 -0
  86. package/dist/visualize/graph-analyzer.js +199 -0
  87. package/dist/visualize/graph-analyzer.js.map +1 -0
  88. package/dist/visualize/html-generator.d.ts +71 -0
  89. package/dist/visualize/html-generator.js +1312 -0
  90. package/dist/visualize/html-generator.js.map +1 -0
  91. package/dist/visualize/json-formatter.d.ts +106 -0
  92. package/dist/visualize/json-formatter.js +252 -0
  93. package/dist/visualize/json-formatter.js.map +1 -0
  94. package/docs/API_REFERENCE.md +747 -0
  95. package/docs/ARCHITECTURE.md +486 -0
  96. package/docs/CLI_GUIDE.md +576 -0
  97. package/docs/HTML_VISUALIZATION.md +365 -0
  98. package/package.json +85 -0
@@ -0,0 +1,91 @@
1
+ import type { ParseEntryFile } from "../parser/parse-entry-file";
2
+ import type { ParseNsModule } from "../parser/parse-ns-module";
3
+ /**
4
+ * Provider scope types
5
+ */
6
+ export type ProviderScope = "Singleton" | "Request";
7
+ /**
8
+ * Information about a provider's scope
9
+ */
10
+ export interface ProviderScopeInfo {
11
+ /** Provider token */
12
+ token: string;
13
+ /** Module that registers this provider */
14
+ module: string;
15
+ /** Provider scope */
16
+ scope: ProviderScope;
17
+ /** Provider type */
18
+ type: "Class" | "UseValue" | "UseFactory" | "UseClass";
19
+ /** Dependencies of this provider */
20
+ dependencies: string[];
21
+ }
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
+ /**
44
+ * Provider scope analysis results
45
+ */
46
+ export interface ProviderScopeAnalysis {
47
+ /** Whether scope analysis was performed */
48
+ hasScopeAnalysis: boolean;
49
+ /** Total number of providers analyzed */
50
+ totalProviders: number;
51
+ /** Number of singleton providers */
52
+ singletonProviders: number;
53
+ /** Number of request-scoped providers */
54
+ requestProviders: number;
55
+ /** Scope mismatches detected */
56
+ scopeMismatches: ScopeMismatch[];
57
+ /** All provider scope information */
58
+ providerScopes: ProviderScopeInfo[];
59
+ }
60
+ /**
61
+ * Analyzes provider scopes and detects scope-related issues
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
67
+ */
68
+ export declare class ProviderScopeAnalyzer {
69
+ private readonly graph;
70
+ constructor(graph: Map<string, ParseNsModule | ParseEntryFile>);
71
+ /**
72
+ * Analyze provider scopes and detect issues
73
+ */
74
+ analyze(): ProviderScopeAnalysis;
75
+ /**
76
+ * Build a map of all providers with their scope information
77
+ */
78
+ private buildProviderScopeMap;
79
+ /**
80
+ * Extract scope from provider
81
+ */
82
+ 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
+ }
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProviderScopeAnalyzer = void 0;
4
+ /**
5
+ * Analyzes provider scopes and detects scope-related issues
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
11
+ */
12
+ class ProviderScopeAnalyzer {
13
+ constructor(graph) {
14
+ this.graph = graph;
15
+ }
16
+ /**
17
+ * Analyze provider scopes and detect issues
18
+ */
19
+ analyze() {
20
+ // Build provider scope map
21
+ const providerScopes = this.buildProviderScopeMap();
22
+ // Detect scope mismatches
23
+ const scopeMismatches = this.detectScopeMismatches(providerScopes);
24
+ // Calculate statistics
25
+ const singletonCount = providerScopes.filter((p) => p.scope === "Singleton").length;
26
+ const requestCount = providerScopes.filter((p) => p.scope === "Request").length;
27
+ return {
28
+ hasScopeAnalysis: true,
29
+ totalProviders: providerScopes.length,
30
+ singletonProviders: singletonCount,
31
+ requestProviders: requestCount,
32
+ scopeMismatches,
33
+ providerScopes,
34
+ };
35
+ }
36
+ /**
37
+ * Build a map of all providers with their scope information
38
+ */
39
+ buildProviderScopeMap() {
40
+ const providerScopes = [];
41
+ for (const [key, value] of this.graph.entries()) {
42
+ if (key === "entry")
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;
50
+ const scope = this.extractProviderScope(provider);
51
+ const dependencies = this.extractDependencyTokens(provider);
52
+ providerScopes.push({
53
+ token: provider.token,
54
+ module: parseNsModule.name || key,
55
+ scope,
56
+ type: provider.type,
57
+ dependencies,
58
+ });
59
+ }
60
+ }
61
+ return providerScopes;
62
+ }
63
+ /**
64
+ * Extract scope from provider
65
+ */
66
+ extractProviderScope(provider) {
67
+ // Check if scope is explicitly defined (applies to all provider types)
68
+ if (provider.scope) {
69
+ const scopeStr = provider.scope.toLowerCase();
70
+ if (scopeStr.includes("request") || scopeStr === "1") {
71
+ return "Request";
72
+ }
73
+ }
74
+ // Default to Singleton for all provider types
75
+ return "Singleton";
76
+ }
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
+ }
136
+ exports.ProviderScopeAnalyzer = ProviderScopeAnalyzer;
137
+ //# sourceMappingURL=provider-scope-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-scope-analyzer.js","sourceRoot":"","sources":["../../src/analyzer/provider-scope-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import type { ParseEntryFile } from "../parser/parse-entry-file";
2
+ import type { ParseNsModule } from "../parser/parse-ns-module";
3
+ /**
4
+ * Information about an unused provider
5
+ */
6
+ export interface UnusedProvider {
7
+ /** Provider token (identifier) */
8
+ token: string;
9
+ /** Module where the provider is registered */
10
+ module: string;
11
+ /** Type of provider */
12
+ type: "Class" | "UseValue" | "UseFactory" | "UseClass";
13
+ /** Severity level */
14
+ severity: "warning" | "info";
15
+ /** Descriptive message */
16
+ message: string;
17
+ /** Suggestions for resolution */
18
+ suggestions: string[];
19
+ }
20
+ /**
21
+ * Analysis results for unused providers
22
+ */
23
+ export interface UnusedProviderAnalysis {
24
+ /** Whether any unused providers were detected */
25
+ hasUnusedProviders: boolean;
26
+ /** List of unused providers */
27
+ unusedProviders: UnusedProvider[];
28
+ /** Total count of unused providers */
29
+ totalUnused: number;
30
+ }
31
+ /**
32
+ * Detects providers that are registered but never injected
33
+ *
34
+ * Analyzes the dependency graph to find providers that are:
35
+ * - Registered in a module's providers array
36
+ * - Not injected as dependencies in any other provider
37
+ * - Not exported from the module (unless they're used internally)
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * const detector = new UnusedProviderDetector(modulesGraph);
42
+ * const analysis = detector.analyze();
43
+ *
44
+ * if (analysis.hasUnusedProviders) {
45
+ * console.log(`Found ${analysis.totalUnused} unused providers`);
46
+ * for (const provider of analysis.unusedProviders) {
47
+ * console.log(`- ${provider.token} in ${provider.module}`);
48
+ * }
49
+ * }
50
+ * ```
51
+ */
52
+ export declare class UnusedProviderDetector {
53
+ private readonly graph;
54
+ constructor(graph: Map<string, ParseNsModule | ParseEntryFile>);
55
+ /**
56
+ * Analyze the graph for unused providers
57
+ *
58
+ * @returns Analysis results containing all unused providers
59
+ */
60
+ analyze(): UnusedProviderAnalysis;
61
+ /**
62
+ * Build a set of all provider tokens that are injected as dependencies
63
+ */
64
+ private buildInjectedTokensSet;
65
+ /**
66
+ * Build a set of all provider tokens that are exported from modules
67
+ */
68
+ private buildExportedTokensSet;
69
+ /**
70
+ * Generate suggestions for resolving an unused provider
71
+ */
72
+ private generateSuggestions;
73
+ }
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UnusedProviderDetector = void 0;
4
+ /**
5
+ * Detects providers that are registered but never injected
6
+ *
7
+ * Analyzes the dependency graph to find providers that are:
8
+ * - Registered in a module's providers array
9
+ * - Not injected as dependencies in any other provider
10
+ * - Not exported from the module (unless they're used internally)
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const detector = new UnusedProviderDetector(modulesGraph);
15
+ * const analysis = detector.analyze();
16
+ *
17
+ * if (analysis.hasUnusedProviders) {
18
+ * console.log(`Found ${analysis.totalUnused} unused providers`);
19
+ * for (const provider of analysis.unusedProviders) {
20
+ * console.log(`- ${provider.token} in ${provider.module}`);
21
+ * }
22
+ * }
23
+ * ```
24
+ */
25
+ class UnusedProviderDetector {
26
+ constructor(graph) {
27
+ this.graph = graph;
28
+ }
29
+ /**
30
+ * Analyze the graph for unused providers
31
+ *
32
+ * @returns Analysis results containing all unused providers
33
+ */
34
+ analyze() {
35
+ const unusedProviders = [];
36
+ // Build a set of all injected provider tokens
37
+ const injectedTokens = this.buildInjectedTokensSet();
38
+ // Build a set of all exported provider tokens
39
+ const exportedTokens = this.buildExportedTokensSet();
40
+ // Check each module for unused providers
41
+ for (const [moduleName, module] of this.graph) {
42
+ if (moduleName === "entry")
43
+ continue;
44
+ const nsModule = module;
45
+ if (!nsModule.providers || nsModule.providers.length === 0)
46
+ continue;
47
+ // Check each provider in the module
48
+ for (const provider of nsModule.providers) {
49
+ const token = provider.token;
50
+ // Skip providers with null tokens
51
+ if (!token)
52
+ continue;
53
+ // Skip if the provider is injected somewhere
54
+ if (injectedTokens.has(token))
55
+ continue;
56
+ // Skip if the provider is exported (it may be used externally)
57
+ if (exportedTokens.has(token))
58
+ continue;
59
+ // Skip if the module is global (providers may be used across the app)
60
+ if (nsModule.isGlobal)
61
+ continue;
62
+ // This provider is unused
63
+ const suggestions = this.generateSuggestions(token, moduleName, exportedTokens.has(token), nsModule.isGlobal);
64
+ // Normalize provider type to match expected union type
65
+ const providerType = provider.type;
66
+ unusedProviders.push({
67
+ token,
68
+ module: moduleName,
69
+ type: providerType,
70
+ severity: "warning",
71
+ message: `Provider '${token}' is registered in '${moduleName}' but never injected`,
72
+ suggestions,
73
+ });
74
+ }
75
+ }
76
+ return {
77
+ hasUnusedProviders: unusedProviders.length > 0,
78
+ unusedProviders,
79
+ totalUnused: unusedProviders.length,
80
+ };
81
+ }
82
+ /**
83
+ * Build a set of all provider tokens that are injected as dependencies
84
+ */
85
+ buildInjectedTokensSet() {
86
+ const injectedTokens = new Set();
87
+ for (const [moduleName, module] of this.graph) {
88
+ if (moduleName === "entry")
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;
97
+ for (const dependency of provider.dependencies) {
98
+ // Skip optional dependencies as they may not be required
99
+ if (!dependency.optional) {
100
+ injectedTokens.add(dependency.token);
101
+ }
102
+ }
103
+ }
104
+ }
105
+ return injectedTokens;
106
+ }
107
+ /**
108
+ * Build a set of all provider tokens that are exported from modules
109
+ */
110
+ buildExportedTokensSet() {
111
+ const exportedTokens = new Set();
112
+ for (const [moduleName, module] of this.graph) {
113
+ if (moduleName === "entry")
114
+ continue;
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);
121
+ }
122
+ }
123
+ return exportedTokens;
124
+ }
125
+ /**
126
+ * Generate suggestions for resolving an unused provider
127
+ */
128
+ generateSuggestions(token, moduleName, isExported, isGlobal) {
129
+ const suggestions = [];
130
+ if (isExported) {
131
+ suggestions.push(`Provider is exported - it may be used outside the analyzed scope`);
132
+ suggestions.push(`If not needed externally, remove '${token}' from the exports array`);
133
+ }
134
+ else if (isGlobal) {
135
+ suggestions.push(`Module is global - provider may be used across the application`);
136
+ suggestions.push(`Verify if '${token}' is actually needed before removing`);
137
+ }
138
+ else {
139
+ suggestions.push(`Remove '${token}' from the providers array in '${moduleName}'`);
140
+ suggestions.push(`Or export it if it's intended to be used by other modules`);
141
+ suggestions.push(`Or inject it somewhere if it provides side effects (e.g., initialization)`);
142
+ }
143
+ return suggestions;
144
+ }
145
+ }
146
+ exports.UnusedProviderDetector = UnusedProviderDetector;
147
+ //# sourceMappingURL=unused-provider-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unused-provider-detector.js","sourceRoot":"","sources":["../../src/analyzer/unused-provider-detector.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};