driftdetect-core 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 (221) hide show
  1. package/dist/analyzers/ast-analyzer.d.ts +251 -0
  2. package/dist/analyzers/ast-analyzer.d.ts.map +1 -0
  3. package/dist/analyzers/ast-analyzer.js +548 -0
  4. package/dist/analyzers/ast-analyzer.js.map +1 -0
  5. package/dist/analyzers/flow-analyzer.d.ts +241 -0
  6. package/dist/analyzers/flow-analyzer.d.ts.map +1 -0
  7. package/dist/analyzers/flow-analyzer.js +1219 -0
  8. package/dist/analyzers/flow-analyzer.js.map +1 -0
  9. package/dist/analyzers/index.d.ts +18 -0
  10. package/dist/analyzers/index.d.ts.map +1 -0
  11. package/dist/analyzers/index.js +19 -0
  12. package/dist/analyzers/index.js.map +1 -0
  13. package/dist/analyzers/semantic-analyzer.d.ts +252 -0
  14. package/dist/analyzers/semantic-analyzer.d.ts.map +1 -0
  15. package/dist/analyzers/semantic-analyzer.js +1182 -0
  16. package/dist/analyzers/semantic-analyzer.js.map +1 -0
  17. package/dist/analyzers/type-analyzer.d.ts +289 -0
  18. package/dist/analyzers/type-analyzer.d.ts.map +1 -0
  19. package/dist/analyzers/type-analyzer.js +1269 -0
  20. package/dist/analyzers/type-analyzer.js.map +1 -0
  21. package/dist/analyzers/types.d.ts +537 -0
  22. package/dist/analyzers/types.d.ts.map +1 -0
  23. package/dist/analyzers/types.js +11 -0
  24. package/dist/analyzers/types.js.map +1 -0
  25. package/dist/config/config-loader.d.ts +166 -0
  26. package/dist/config/config-loader.d.ts.map +1 -0
  27. package/dist/config/config-loader.js +429 -0
  28. package/dist/config/config-loader.js.map +1 -0
  29. package/dist/config/config-validator.d.ts +204 -0
  30. package/dist/config/config-validator.d.ts.map +1 -0
  31. package/dist/config/config-validator.js +632 -0
  32. package/dist/config/config-validator.js.map +1 -0
  33. package/dist/config/defaults.d.ts +8 -0
  34. package/dist/config/defaults.d.ts.map +1 -0
  35. package/dist/config/defaults.js +26 -0
  36. package/dist/config/defaults.js.map +1 -0
  37. package/dist/config/index.d.ts +10 -0
  38. package/dist/config/index.d.ts.map +1 -0
  39. package/dist/config/index.js +10 -0
  40. package/dist/config/index.js.map +1 -0
  41. package/dist/config/types.d.ts +47 -0
  42. package/dist/config/types.d.ts.map +1 -0
  43. package/dist/config/types.js +7 -0
  44. package/dist/config/types.js.map +1 -0
  45. package/dist/index.d.ts +37 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +39 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/manifest/exporter.d.ts +21 -0
  50. package/dist/manifest/exporter.d.ts.map +1 -0
  51. package/dist/manifest/exporter.js +339 -0
  52. package/dist/manifest/exporter.js.map +1 -0
  53. package/dist/manifest/index.d.ts +14 -0
  54. package/dist/manifest/index.d.ts.map +1 -0
  55. package/dist/manifest/index.js +15 -0
  56. package/dist/manifest/index.js.map +1 -0
  57. package/dist/manifest/manifest-store.d.ts +111 -0
  58. package/dist/manifest/manifest-store.d.ts.map +1 -0
  59. package/dist/manifest/manifest-store.js +418 -0
  60. package/dist/manifest/manifest-store.js.map +1 -0
  61. package/dist/manifest/types.d.ts +238 -0
  62. package/dist/manifest/types.d.ts.map +1 -0
  63. package/dist/manifest/types.js +11 -0
  64. package/dist/manifest/types.js.map +1 -0
  65. package/dist/matcher/confidence-scorer.d.ts +188 -0
  66. package/dist/matcher/confidence-scorer.d.ts.map +1 -0
  67. package/dist/matcher/confidence-scorer.js +302 -0
  68. package/dist/matcher/confidence-scorer.js.map +1 -0
  69. package/dist/matcher/index.d.ts +24 -0
  70. package/dist/matcher/index.d.ts.map +1 -0
  71. package/dist/matcher/index.js +26 -0
  72. package/dist/matcher/index.js.map +1 -0
  73. package/dist/matcher/outlier-detector.d.ts +252 -0
  74. package/dist/matcher/outlier-detector.d.ts.map +1 -0
  75. package/dist/matcher/outlier-detector.js +544 -0
  76. package/dist/matcher/outlier-detector.js.map +1 -0
  77. package/dist/matcher/pattern-matcher.d.ts +169 -0
  78. package/dist/matcher/pattern-matcher.d.ts.map +1 -0
  79. package/dist/matcher/pattern-matcher.js +692 -0
  80. package/dist/matcher/pattern-matcher.js.map +1 -0
  81. package/dist/matcher/types.d.ts +476 -0
  82. package/dist/matcher/types.d.ts.map +1 -0
  83. package/dist/matcher/types.js +36 -0
  84. package/dist/matcher/types.js.map +1 -0
  85. package/dist/parsers/base-parser.d.ts +282 -0
  86. package/dist/parsers/base-parser.d.ts.map +1 -0
  87. package/dist/parsers/base-parser.js +421 -0
  88. package/dist/parsers/base-parser.js.map +1 -0
  89. package/dist/parsers/css-parser.d.ts +225 -0
  90. package/dist/parsers/css-parser.d.ts.map +1 -0
  91. package/dist/parsers/css-parser.js +477 -0
  92. package/dist/parsers/css-parser.js.map +1 -0
  93. package/dist/parsers/index.d.ts +15 -0
  94. package/dist/parsers/index.d.ts.map +1 -0
  95. package/dist/parsers/index.js +15 -0
  96. package/dist/parsers/index.js.map +1 -0
  97. package/dist/parsers/json-parser.d.ts +219 -0
  98. package/dist/parsers/json-parser.d.ts.map +1 -0
  99. package/dist/parsers/json-parser.js +602 -0
  100. package/dist/parsers/json-parser.js.map +1 -0
  101. package/dist/parsers/markdown-parser.d.ts +276 -0
  102. package/dist/parsers/markdown-parser.d.ts.map +1 -0
  103. package/dist/parsers/markdown-parser.js +731 -0
  104. package/dist/parsers/markdown-parser.js.map +1 -0
  105. package/dist/parsers/parser-manager.d.ts +294 -0
  106. package/dist/parsers/parser-manager.d.ts.map +1 -0
  107. package/dist/parsers/parser-manager.js +738 -0
  108. package/dist/parsers/parser-manager.js.map +1 -0
  109. package/dist/parsers/python-parser.d.ts +204 -0
  110. package/dist/parsers/python-parser.d.ts.map +1 -0
  111. package/dist/parsers/python-parser.js +517 -0
  112. package/dist/parsers/python-parser.js.map +1 -0
  113. package/dist/parsers/types.d.ts +43 -0
  114. package/dist/parsers/types.d.ts.map +1 -0
  115. package/dist/parsers/types.js +7 -0
  116. package/dist/parsers/types.js.map +1 -0
  117. package/dist/parsers/typescript-parser.d.ts +264 -0
  118. package/dist/parsers/typescript-parser.d.ts.map +1 -0
  119. package/dist/parsers/typescript-parser.js +658 -0
  120. package/dist/parsers/typescript-parser.js.map +1 -0
  121. package/dist/rules/evaluator.d.ts +305 -0
  122. package/dist/rules/evaluator.d.ts.map +1 -0
  123. package/dist/rules/evaluator.js +579 -0
  124. package/dist/rules/evaluator.js.map +1 -0
  125. package/dist/rules/index.d.ts +13 -0
  126. package/dist/rules/index.d.ts.map +1 -0
  127. package/dist/rules/index.js +13 -0
  128. package/dist/rules/index.js.map +1 -0
  129. package/dist/rules/quick-fix-generator.d.ts +334 -0
  130. package/dist/rules/quick-fix-generator.d.ts.map +1 -0
  131. package/dist/rules/quick-fix-generator.js +1075 -0
  132. package/dist/rules/quick-fix-generator.js.map +1 -0
  133. package/dist/rules/rule-engine.d.ts +241 -0
  134. package/dist/rules/rule-engine.d.ts.map +1 -0
  135. package/dist/rules/rule-engine.js +585 -0
  136. package/dist/rules/rule-engine.js.map +1 -0
  137. package/dist/rules/severity-manager.d.ts +394 -0
  138. package/dist/rules/severity-manager.d.ts.map +1 -0
  139. package/dist/rules/severity-manager.js +619 -0
  140. package/dist/rules/severity-manager.js.map +1 -0
  141. package/dist/rules/types.d.ts +370 -0
  142. package/dist/rules/types.d.ts.map +1 -0
  143. package/dist/rules/types.js +133 -0
  144. package/dist/rules/types.js.map +1 -0
  145. package/dist/rules/variant-manager.d.ts +388 -0
  146. package/dist/rules/variant-manager.d.ts.map +1 -0
  147. package/dist/rules/variant-manager.js +777 -0
  148. package/dist/rules/variant-manager.js.map +1 -0
  149. package/dist/scanner/change-detector.d.ts +164 -0
  150. package/dist/scanner/change-detector.d.ts.map +1 -0
  151. package/dist/scanner/change-detector.js +263 -0
  152. package/dist/scanner/change-detector.js.map +1 -0
  153. package/dist/scanner/dependency-graph.d.ts +270 -0
  154. package/dist/scanner/dependency-graph.d.ts.map +1 -0
  155. package/dist/scanner/dependency-graph.js +436 -0
  156. package/dist/scanner/dependency-graph.js.map +1 -0
  157. package/dist/scanner/file-walker.d.ts +127 -0
  158. package/dist/scanner/file-walker.d.ts.map +1 -0
  159. package/dist/scanner/file-walker.js +526 -0
  160. package/dist/scanner/file-walker.js.map +1 -0
  161. package/dist/scanner/index.d.ts +12 -0
  162. package/dist/scanner/index.d.ts.map +1 -0
  163. package/dist/scanner/index.js +12 -0
  164. package/dist/scanner/index.js.map +1 -0
  165. package/dist/scanner/types.d.ts +218 -0
  166. package/dist/scanner/types.d.ts.map +1 -0
  167. package/dist/scanner/types.js +10 -0
  168. package/dist/scanner/types.js.map +1 -0
  169. package/dist/scanner/worker-pool.d.ts +317 -0
  170. package/dist/scanner/worker-pool.d.ts.map +1 -0
  171. package/dist/scanner/worker-pool.js +571 -0
  172. package/dist/scanner/worker-pool.js.map +1 -0
  173. package/dist/store/cache-manager.d.ts +179 -0
  174. package/dist/store/cache-manager.d.ts.map +1 -0
  175. package/dist/store/cache-manager.js +391 -0
  176. package/dist/store/cache-manager.js.map +1 -0
  177. package/dist/store/history-store.d.ts +314 -0
  178. package/dist/store/history-store.d.ts.map +1 -0
  179. package/dist/store/history-store.js +707 -0
  180. package/dist/store/history-store.js.map +1 -0
  181. package/dist/store/index.d.ts +20 -0
  182. package/dist/store/index.d.ts.map +1 -0
  183. package/dist/store/index.js +26 -0
  184. package/dist/store/index.js.map +1 -0
  185. package/dist/store/lock-file-manager.d.ts +202 -0
  186. package/dist/store/lock-file-manager.d.ts.map +1 -0
  187. package/dist/store/lock-file-manager.js +475 -0
  188. package/dist/store/lock-file-manager.js.map +1 -0
  189. package/dist/store/pattern-store.d.ts +289 -0
  190. package/dist/store/pattern-store.d.ts.map +1 -0
  191. package/dist/store/pattern-store.js +936 -0
  192. package/dist/store/pattern-store.js.map +1 -0
  193. package/dist/store/schema-validator.d.ts +159 -0
  194. package/dist/store/schema-validator.d.ts.map +1 -0
  195. package/dist/store/schema-validator.js +1096 -0
  196. package/dist/store/schema-validator.js.map +1 -0
  197. package/dist/store/types.d.ts +585 -0
  198. package/dist/store/types.d.ts.map +1 -0
  199. package/dist/store/types.js +82 -0
  200. package/dist/store/types.js.map +1 -0
  201. package/dist/types/analysis.d.ts +19 -0
  202. package/dist/types/analysis.d.ts.map +1 -0
  203. package/dist/types/analysis.js +5 -0
  204. package/dist/types/analysis.js.map +1 -0
  205. package/dist/types/common.d.ts +7 -0
  206. package/dist/types/common.d.ts.map +1 -0
  207. package/dist/types/common.js +5 -0
  208. package/dist/types/common.js.map +1 -0
  209. package/dist/types/index.d.ts +12 -0
  210. package/dist/types/index.d.ts.map +1 -0
  211. package/dist/types/index.js +10 -0
  212. package/dist/types/index.js.map +1 -0
  213. package/dist/types/patterns.d.ts +40 -0
  214. package/dist/types/patterns.d.ts.map +1 -0
  215. package/dist/types/patterns.js +7 -0
  216. package/dist/types/patterns.js.map +1 -0
  217. package/dist/types/violations.d.ts +7 -0
  218. package/dist/types/violations.d.ts.map +1 -0
  219. package/dist/types/violations.js +7 -0
  220. package/dist/types/violations.js.map +1 -0
  221. package/package.json +46 -0
@@ -0,0 +1,270 @@
1
+ /**
2
+ * Dependency Graph - Import/export relationship tracking
3
+ *
4
+ * Builds and maintains a graph of module dependencies,
5
+ * enabling circular dependency detection and topological sorting.
6
+ *
7
+ * @requirements 2.3 - THE Scanner SHALL build and maintain a dependency graph of imports/exports
8
+ * @requirements 2.4 - THE Scanner SHALL detect circular dependencies and flag them
9
+ */
10
+ /**
11
+ * Type of import statement
12
+ */
13
+ export type ImportType = 'es-module' | 'commonjs' | 'dynamic' | 'type-only';
14
+ /**
15
+ * Type of export statement
16
+ */
17
+ export type ExportType = 'named' | 'default' | 're-export' | 'namespace' | 'type-only';
18
+ /**
19
+ * Information about an import statement
20
+ */
21
+ export interface ImportInfo {
22
+ /** The source module path (as written in the import statement) */
23
+ source: string;
24
+ /** Resolved absolute path to the imported module (if resolvable) */
25
+ resolvedPath?: string;
26
+ /** Imported specifiers (e.g., ['foo', 'bar'] for import { foo, bar }) */
27
+ specifiers: ImportSpecifier[];
28
+ /** Type of import */
29
+ type: ImportType;
30
+ /** Whether this is a side-effect only import (import './styles.css') */
31
+ sideEffectOnly: boolean;
32
+ /** Line number where the import appears */
33
+ line: number;
34
+ /** Column number where the import appears */
35
+ column: number;
36
+ }
37
+ /**
38
+ * Individual import specifier
39
+ */
40
+ export interface ImportSpecifier {
41
+ /** Name as exported from the source module */
42
+ imported: string;
43
+ /** Local name in the importing module (may differ due to aliasing) */
44
+ local: string;
45
+ /** Whether this is a default import */
46
+ isDefault: boolean;
47
+ /** Whether this is a namespace import (import * as foo) */
48
+ isNamespace: boolean;
49
+ }
50
+ /**
51
+ * Information about an export statement
52
+ */
53
+ export interface ExportInfo {
54
+ /** Name of the exported symbol */
55
+ name: string;
56
+ /** Type of export */
57
+ type: ExportType;
58
+ /** Source module for re-exports */
59
+ source?: string;
60
+ /** Original name if re-exported with alias */
61
+ originalName?: string;
62
+ /** Line number where the export appears */
63
+ line: number;
64
+ /** Column number where the export appears */
65
+ column: number;
66
+ }
67
+ /**
68
+ * Represents a module (file) in the dependency graph
69
+ */
70
+ export interface ModuleNode {
71
+ /** Absolute path to the module */
72
+ path: string;
73
+ /** All imports in this module */
74
+ imports: ImportInfo[];
75
+ /** All exports from this module */
76
+ exports: ExportInfo[];
77
+ /** Paths of modules this module imports (dependencies) */
78
+ dependencies: Set<string>;
79
+ /** Paths of modules that import this module (dependents) */
80
+ dependents: Set<string>;
81
+ /** Whether this module has been fully analyzed */
82
+ analyzed: boolean;
83
+ /** Last modification time when analyzed */
84
+ analyzedAt?: Date;
85
+ }
86
+ /**
87
+ * Represents an edge in the dependency graph
88
+ */
89
+ export interface DependencyEdge {
90
+ /** Source module (the one doing the importing) */
91
+ from: string;
92
+ /** Target module (the one being imported) */
93
+ to: string;
94
+ /** Import information for this edge */
95
+ importInfo: ImportInfo;
96
+ }
97
+ /**
98
+ * Result of circular dependency detection
99
+ */
100
+ export interface CircularDependencyResult {
101
+ /** Whether any circular dependencies were found */
102
+ hasCircular: boolean;
103
+ /** All detected cycles (each cycle is an array of file paths) */
104
+ cycles: string[][];
105
+ }
106
+ /**
107
+ * Options for dependency graph operations
108
+ */
109
+ export interface DependencyGraphOptions {
110
+ /** Whether to track type-only imports separately */
111
+ trackTypeImports?: boolean;
112
+ /** Whether to include node_modules in the graph */
113
+ includeNodeModules?: boolean;
114
+ }
115
+ /**
116
+ * Dependency Graph class for tracking module relationships
117
+ *
118
+ * @requirements 2.3 - Build and maintain a dependency graph of imports/exports
119
+ * @requirements 2.4 - Detect circular dependencies and flag them
120
+ */
121
+ export declare class DependencyGraph {
122
+ /** Map of module path to module node */
123
+ private modules;
124
+ /** All edges in the graph */
125
+ private edges;
126
+ /** Configuration options */
127
+ private options;
128
+ constructor(options?: DependencyGraphOptions);
129
+ /**
130
+ * Add a module to the dependency graph
131
+ *
132
+ * @param path - Absolute path to the module
133
+ * @param imports - Import statements in the module
134
+ * @param exports - Export statements in the module
135
+ */
136
+ addModule(path: string, imports: ImportInfo[], exports: ExportInfo[]): void;
137
+ /**
138
+ * Remove a module from the dependency graph
139
+ *
140
+ * @param path - Absolute path to the module to remove
141
+ */
142
+ removeModule(path: string): void;
143
+ /**
144
+ * Get all modules that this module imports (direct dependencies)
145
+ *
146
+ * @param path - Absolute path to the module
147
+ * @returns Array of paths to dependencies
148
+ */
149
+ getDependencies(path: string): string[];
150
+ /**
151
+ * Get all modules that import this module (direct dependents)
152
+ *
153
+ * @param path - Absolute path to the module
154
+ * @returns Array of paths to dependents
155
+ */
156
+ getDependents(path: string): string[];
157
+ /**
158
+ * Get all transitive dependencies of a module (recursive)
159
+ *
160
+ * @param path - Absolute path to the module
161
+ * @returns Array of all transitive dependency paths
162
+ */
163
+ getTransitiveDependencies(path: string): string[];
164
+ /**
165
+ * Get all transitive dependents of a module (recursive)
166
+ *
167
+ * @param path - Absolute path to the module
168
+ * @returns Array of all transitive dependent paths
169
+ */
170
+ getTransitiveDependents(path: string): string[];
171
+ /**
172
+ * Get modules in topological order (build order)
173
+ * Modules with no dependencies come first
174
+ *
175
+ * @returns Array of module paths in topological order
176
+ * @throws Error if the graph contains cycles
177
+ */
178
+ getTopologicalOrder(): string[];
179
+ /**
180
+ * Check if the graph has any circular dependencies
181
+ *
182
+ * @returns true if circular dependencies exist
183
+ * @requirements 2.4
184
+ */
185
+ hasCircularDependency(): boolean;
186
+ /**
187
+ * Get all circular dependencies in the graph
188
+ *
189
+ * @returns Array of cycles, where each cycle is an array of file paths
190
+ * @requirements 2.4
191
+ */
192
+ getCircularDependencies(): string[][];
193
+ /**
194
+ * Get detailed circular dependency information
195
+ *
196
+ * @returns CircularDependencyResult with all cycles
197
+ * @requirements 2.4
198
+ */
199
+ detectCircularDependencies(): CircularDependencyResult;
200
+ /**
201
+ * Get a module node by path
202
+ *
203
+ * @param path - Absolute path to the module
204
+ * @returns ModuleNode or undefined if not found
205
+ */
206
+ getModule(path: string): ModuleNode | undefined;
207
+ /**
208
+ * Check if a module exists in the graph
209
+ *
210
+ * @param path - Absolute path to the module
211
+ * @returns true if the module exists
212
+ */
213
+ hasModule(path: string): boolean;
214
+ /**
215
+ * Get all modules in the graph
216
+ *
217
+ * @returns Array of all module paths
218
+ */
219
+ getAllModules(): string[];
220
+ /**
221
+ * Get all edges in the graph
222
+ *
223
+ * @returns Array of all dependency edges
224
+ */
225
+ getAllEdges(): DependencyEdge[];
226
+ /**
227
+ * Get the number of modules in the graph
228
+ */
229
+ get size(): number;
230
+ /**
231
+ * Get the number of edges in the graph
232
+ */
233
+ get edgeCount(): number;
234
+ /**
235
+ * Clear all modules and edges from the graph
236
+ */
237
+ clear(): void;
238
+ /**
239
+ * Get modules with no dependencies (leaf nodes)
240
+ *
241
+ * @returns Array of module paths with no dependencies
242
+ */
243
+ getLeafModules(): string[];
244
+ /**
245
+ * Get modules with no dependents (root nodes)
246
+ *
247
+ * @returns Array of module paths with no dependents
248
+ */
249
+ getRootModules(): string[];
250
+ /**
251
+ * Get modules that are part of any circular dependency
252
+ *
253
+ * @returns Array of module paths involved in cycles
254
+ */
255
+ getModulesInCycles(): string[];
256
+ /**
257
+ * Check if a specific cycle already exists in the cycles array
258
+ * Cycles are considered equal if they contain the same nodes
259
+ */
260
+ private cycleExists;
261
+ /**
262
+ * Normalize a file path for consistent comparison
263
+ */
264
+ private normalizePath;
265
+ /**
266
+ * Check if an import source is a node_modules package
267
+ */
268
+ private isNodeModule;
269
+ }
270
+ //# sourceMappingURL=dependency-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-graph.d.ts","sourceRoot":"","sources":["../../src/scanner/dependency-graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,436 @@
1
+ /**
2
+ * Dependency Graph - Import/export relationship tracking
3
+ *
4
+ * Builds and maintains a graph of module dependencies,
5
+ * enabling circular dependency detection and topological sorting.
6
+ *
7
+ * @requirements 2.3 - THE Scanner SHALL build and maintain a dependency graph of imports/exports
8
+ * @requirements 2.4 - THE Scanner SHALL detect circular dependencies and flag them
9
+ */
10
+ /**
11
+ * Dependency Graph class for tracking module relationships
12
+ *
13
+ * @requirements 2.3 - Build and maintain a dependency graph of imports/exports
14
+ * @requirements 2.4 - Detect circular dependencies and flag them
15
+ */
16
+ export class DependencyGraph {
17
+ /** Map of module path to module node */
18
+ modules = new Map();
19
+ /** All edges in the graph */
20
+ edges = [];
21
+ /** Configuration options */
22
+ options;
23
+ constructor(options = {}) {
24
+ this.options = {
25
+ trackTypeImports: true,
26
+ includeNodeModules: false,
27
+ ...options,
28
+ };
29
+ }
30
+ /**
31
+ * Add a module to the dependency graph
32
+ *
33
+ * @param path - Absolute path to the module
34
+ * @param imports - Import statements in the module
35
+ * @param exports - Export statements in the module
36
+ */
37
+ addModule(path, imports, exports) {
38
+ const normalizedPath = this.normalizePath(path);
39
+ // Filter imports based on options
40
+ const filteredImports = imports.filter((imp) => {
41
+ if (!this.options.trackTypeImports && imp.type === 'type-only') {
42
+ return false;
43
+ }
44
+ if (!this.options.includeNodeModules && this.isNodeModule(imp.source)) {
45
+ return false;
46
+ }
47
+ return true;
48
+ });
49
+ // Create or update the module node
50
+ const existingNode = this.modules.get(normalizedPath);
51
+ const dependencies = new Set();
52
+ // Build dependency set from imports
53
+ for (const imp of filteredImports) {
54
+ if (imp.resolvedPath) {
55
+ const resolvedNormalized = this.normalizePath(imp.resolvedPath);
56
+ dependencies.add(resolvedNormalized);
57
+ // Add edge
58
+ this.edges.push({
59
+ from: normalizedPath,
60
+ to: resolvedNormalized,
61
+ importInfo: imp,
62
+ });
63
+ // Update the dependent's dependents set
64
+ const targetModule = this.modules.get(resolvedNormalized);
65
+ if (targetModule) {
66
+ targetModule.dependents.add(normalizedPath);
67
+ }
68
+ else {
69
+ // Create a placeholder node for the target
70
+ this.modules.set(resolvedNormalized, {
71
+ path: resolvedNormalized,
72
+ imports: [],
73
+ exports: [],
74
+ dependencies: new Set(),
75
+ dependents: new Set([normalizedPath]),
76
+ analyzed: false,
77
+ });
78
+ }
79
+ }
80
+ }
81
+ const moduleNode = {
82
+ path: normalizedPath,
83
+ imports: filteredImports,
84
+ exports,
85
+ dependencies,
86
+ dependents: existingNode?.dependents ?? new Set(),
87
+ analyzed: true,
88
+ analyzedAt: new Date(),
89
+ };
90
+ this.modules.set(normalizedPath, moduleNode);
91
+ }
92
+ /**
93
+ * Remove a module from the dependency graph
94
+ *
95
+ * @param path - Absolute path to the module to remove
96
+ */
97
+ removeModule(path) {
98
+ const normalizedPath = this.normalizePath(path);
99
+ const module = this.modules.get(normalizedPath);
100
+ if (!module) {
101
+ return;
102
+ }
103
+ // Remove this module from all dependents' dependency sets
104
+ for (const dependent of module.dependents) {
105
+ const dependentModule = this.modules.get(dependent);
106
+ if (dependentModule) {
107
+ dependentModule.dependencies.delete(normalizedPath);
108
+ }
109
+ }
110
+ // Remove this module from all dependencies' dependent sets
111
+ for (const dependency of module.dependencies) {
112
+ const dependencyModule = this.modules.get(dependency);
113
+ if (dependencyModule) {
114
+ dependencyModule.dependents.delete(normalizedPath);
115
+ }
116
+ }
117
+ // Remove edges involving this module
118
+ this.edges = this.edges.filter((edge) => edge.from !== normalizedPath && edge.to !== normalizedPath);
119
+ // Remove the module
120
+ this.modules.delete(normalizedPath);
121
+ }
122
+ /**
123
+ * Get all modules that this module imports (direct dependencies)
124
+ *
125
+ * @param path - Absolute path to the module
126
+ * @returns Array of paths to dependencies
127
+ */
128
+ getDependencies(path) {
129
+ const normalizedPath = this.normalizePath(path);
130
+ const module = this.modules.get(normalizedPath);
131
+ if (!module) {
132
+ return [];
133
+ }
134
+ return Array.from(module.dependencies);
135
+ }
136
+ /**
137
+ * Get all modules that import this module (direct dependents)
138
+ *
139
+ * @param path - Absolute path to the module
140
+ * @returns Array of paths to dependents
141
+ */
142
+ getDependents(path) {
143
+ const normalizedPath = this.normalizePath(path);
144
+ const module = this.modules.get(normalizedPath);
145
+ if (!module) {
146
+ return [];
147
+ }
148
+ return Array.from(module.dependents);
149
+ }
150
+ /**
151
+ * Get all transitive dependencies of a module (recursive)
152
+ *
153
+ * @param path - Absolute path to the module
154
+ * @returns Array of all transitive dependency paths
155
+ */
156
+ getTransitiveDependencies(path) {
157
+ const normalizedPath = this.normalizePath(path);
158
+ const visited = new Set();
159
+ const result = [];
160
+ const visit = (modulePath) => {
161
+ if (visited.has(modulePath)) {
162
+ return;
163
+ }
164
+ visited.add(modulePath);
165
+ const module = this.modules.get(modulePath);
166
+ if (!module) {
167
+ return;
168
+ }
169
+ for (const dep of module.dependencies) {
170
+ if (dep !== normalizedPath) {
171
+ result.push(dep);
172
+ visit(dep);
173
+ }
174
+ }
175
+ };
176
+ visit(normalizedPath);
177
+ return result;
178
+ }
179
+ /**
180
+ * Get all transitive dependents of a module (recursive)
181
+ *
182
+ * @param path - Absolute path to the module
183
+ * @returns Array of all transitive dependent paths
184
+ */
185
+ getTransitiveDependents(path) {
186
+ const normalizedPath = this.normalizePath(path);
187
+ const visited = new Set();
188
+ const result = [];
189
+ const visit = (modulePath) => {
190
+ if (visited.has(modulePath)) {
191
+ return;
192
+ }
193
+ visited.add(modulePath);
194
+ const module = this.modules.get(modulePath);
195
+ if (!module) {
196
+ return;
197
+ }
198
+ for (const dependent of module.dependents) {
199
+ if (dependent !== normalizedPath) {
200
+ result.push(dependent);
201
+ visit(dependent);
202
+ }
203
+ }
204
+ };
205
+ visit(normalizedPath);
206
+ return result;
207
+ }
208
+ /**
209
+ * Get modules in topological order (build order)
210
+ * Modules with no dependencies come first
211
+ *
212
+ * @returns Array of module paths in topological order
213
+ * @throws Error if the graph contains cycles
214
+ */
215
+ getTopologicalOrder() {
216
+ const result = [];
217
+ const visited = new Set();
218
+ const visiting = new Set(); // For cycle detection
219
+ const visit = (path) => {
220
+ if (visited.has(path)) {
221
+ return;
222
+ }
223
+ if (visiting.has(path)) {
224
+ throw new Error(`Circular dependency detected involving: ${path}`);
225
+ }
226
+ visiting.add(path);
227
+ const module = this.modules.get(path);
228
+ if (module) {
229
+ for (const dep of module.dependencies) {
230
+ visit(dep);
231
+ }
232
+ }
233
+ visiting.delete(path);
234
+ visited.add(path);
235
+ result.push(path);
236
+ };
237
+ // Visit all modules
238
+ for (const path of this.modules.keys()) {
239
+ visit(path);
240
+ }
241
+ return result;
242
+ }
243
+ /**
244
+ * Check if the graph has any circular dependencies
245
+ *
246
+ * @returns true if circular dependencies exist
247
+ * @requirements 2.4
248
+ */
249
+ hasCircularDependency() {
250
+ return this.getCircularDependencies().length > 0;
251
+ }
252
+ /**
253
+ * Get all circular dependencies in the graph
254
+ *
255
+ * @returns Array of cycles, where each cycle is an array of file paths
256
+ * @requirements 2.4
257
+ */
258
+ getCircularDependencies() {
259
+ const cycles = [];
260
+ const visited = new Set();
261
+ const recursionStack = new Set();
262
+ const path = [];
263
+ const dfs = (node) => {
264
+ visited.add(node);
265
+ recursionStack.add(node);
266
+ path.push(node);
267
+ const module = this.modules.get(node);
268
+ if (module) {
269
+ for (const neighbor of module.dependencies) {
270
+ if (!visited.has(neighbor)) {
271
+ dfs(neighbor);
272
+ }
273
+ else if (recursionStack.has(neighbor)) {
274
+ // Found a cycle - extract it from the path
275
+ const cycleStart = path.indexOf(neighbor);
276
+ if (cycleStart !== -1) {
277
+ const cycle = [...path.slice(cycleStart), neighbor];
278
+ // Only add if this cycle hasn't been found before
279
+ if (!this.cycleExists(cycles, cycle)) {
280
+ cycles.push(cycle);
281
+ }
282
+ }
283
+ }
284
+ }
285
+ }
286
+ path.pop();
287
+ recursionStack.delete(node);
288
+ };
289
+ // Run DFS from each unvisited node
290
+ for (const node of this.modules.keys()) {
291
+ if (!visited.has(node)) {
292
+ dfs(node);
293
+ }
294
+ }
295
+ return cycles;
296
+ }
297
+ /**
298
+ * Get detailed circular dependency information
299
+ *
300
+ * @returns CircularDependencyResult with all cycles
301
+ * @requirements 2.4
302
+ */
303
+ detectCircularDependencies() {
304
+ const cycles = this.getCircularDependencies();
305
+ return {
306
+ hasCircular: cycles.length > 0,
307
+ cycles,
308
+ };
309
+ }
310
+ /**
311
+ * Get a module node by path
312
+ *
313
+ * @param path - Absolute path to the module
314
+ * @returns ModuleNode or undefined if not found
315
+ */
316
+ getModule(path) {
317
+ return this.modules.get(this.normalizePath(path));
318
+ }
319
+ /**
320
+ * Check if a module exists in the graph
321
+ *
322
+ * @param path - Absolute path to the module
323
+ * @returns true if the module exists
324
+ */
325
+ hasModule(path) {
326
+ return this.modules.has(this.normalizePath(path));
327
+ }
328
+ /**
329
+ * Get all modules in the graph
330
+ *
331
+ * @returns Array of all module paths
332
+ */
333
+ getAllModules() {
334
+ return Array.from(this.modules.keys());
335
+ }
336
+ /**
337
+ * Get all edges in the graph
338
+ *
339
+ * @returns Array of all dependency edges
340
+ */
341
+ getAllEdges() {
342
+ return [...this.edges];
343
+ }
344
+ /**
345
+ * Get the number of modules in the graph
346
+ */
347
+ get size() {
348
+ return this.modules.size;
349
+ }
350
+ /**
351
+ * Get the number of edges in the graph
352
+ */
353
+ get edgeCount() {
354
+ return this.edges.length;
355
+ }
356
+ /**
357
+ * Clear all modules and edges from the graph
358
+ */
359
+ clear() {
360
+ this.modules.clear();
361
+ this.edges = [];
362
+ }
363
+ /**
364
+ * Get modules with no dependencies (leaf nodes)
365
+ *
366
+ * @returns Array of module paths with no dependencies
367
+ */
368
+ getLeafModules() {
369
+ const result = [];
370
+ for (const [path, module] of this.modules) {
371
+ if (module.dependencies.size === 0) {
372
+ result.push(path);
373
+ }
374
+ }
375
+ return result;
376
+ }
377
+ /**
378
+ * Get modules with no dependents (root nodes)
379
+ *
380
+ * @returns Array of module paths with no dependents
381
+ */
382
+ getRootModules() {
383
+ const result = [];
384
+ for (const [path, module] of this.modules) {
385
+ if (module.dependents.size === 0) {
386
+ result.push(path);
387
+ }
388
+ }
389
+ return result;
390
+ }
391
+ /**
392
+ * Get modules that are part of any circular dependency
393
+ *
394
+ * @returns Array of module paths involved in cycles
395
+ */
396
+ getModulesInCycles() {
397
+ const cycles = this.getCircularDependencies();
398
+ const modulesInCycles = new Set();
399
+ for (const cycle of cycles) {
400
+ for (const module of cycle) {
401
+ modulesInCycles.add(module);
402
+ }
403
+ }
404
+ return Array.from(modulesInCycles);
405
+ }
406
+ /**
407
+ * Check if a specific cycle already exists in the cycles array
408
+ * Cycles are considered equal if they contain the same nodes
409
+ */
410
+ cycleExists(cycles, newCycle) {
411
+ const newCycleSet = new Set(newCycle.slice(0, -1)); // Exclude the repeated node at the end
412
+ for (const existingCycle of cycles) {
413
+ const existingSet = new Set(existingCycle.slice(0, -1));
414
+ if (existingSet.size === newCycleSet.size &&
415
+ [...newCycleSet].every((node) => existingSet.has(node))) {
416
+ return true;
417
+ }
418
+ }
419
+ return false;
420
+ }
421
+ /**
422
+ * Normalize a file path for consistent comparison
423
+ */
424
+ normalizePath(path) {
425
+ // Normalize path separators and remove trailing slashes
426
+ return path.replace(/\\/g, '/').replace(/\/+$/, '');
427
+ }
428
+ /**
429
+ * Check if an import source is a node_modules package
430
+ */
431
+ isNodeModule(source) {
432
+ // Node modules don't start with . or /
433
+ return !source.startsWith('.') && !source.startsWith('/');
434
+ }
435
+ }
436
+ //# sourceMappingURL=dependency-graph.js.map