@ts-stack/cycle-detector 1.1.0 → 1.1.2
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/README.md +55 -57
- package/dist/index.js +250 -151
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/src/index.ts +259 -167
package/README.md
CHANGED
|
@@ -1,8 +1,60 @@
|
|
|
1
1
|
# Execution-Aware Circular Dependency Detector for TypeScript
|
|
2
2
|
|
|
3
|
-
`@ts-
|
|
3
|
+
`@ts-stack/cycle-detector` - this is a high-performance static analysis utility powered by the native TypeScript Compiler API. Unlike generic dependency visualizers, this tool evaluates the **runtime execution risk** of circular dependencies in monorepos and complex TypeScript applications, isolating architectural flaws from safe, deferred imports.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Installation & Usage
|
|
6
|
+
|
|
7
|
+
You don't even need to install it! Just run it via `npx`:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @ts-stack/cycle-detector src/index.ts
|
|
11
|
+
# OR
|
|
12
|
+
npx @ts-stack/cycle-detector packages/*/src/index.ts
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
But you can install it locally:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -D @ts-stack/cycle-detector
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
In your `package.json`:
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
"scripts": {
|
|
26
|
+
"lint:cycles": "cycle-detector packages/*/src/index.ts"
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
And then:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm run lint:cycles
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Interpreting Diagnostics
|
|
37
|
+
|
|
38
|
+
When a breaking circular dependency is detected, the script identifies exactly **which file executes the token prematurely**, leaving non-blocking files clearly marked.
|
|
39
|
+
|
|
40
|
+
```txt
|
|
41
|
+
❌ [/packages/rest/src/index.ts] — Found 1 critical circular dependencies:
|
|
42
|
+
1) --------------------------------------------------------------------------------
|
|
43
|
+
⏳ [Lazy] /srv/git/ditsmod/ditsmod/packages/rest/src/extensions/routes.extension.ts
|
|
44
|
+
⏳ [Lazy] /srv/git/ditsmod/ditsmod/packages/rest/src/decorators/rest-init-hooks-and-metadata.ts
|
|
45
|
+
💥 [Top-level] /srv/git/ditsmod/ditsmod/packages/rest/src/init/rest.module.ts
|
|
46
|
+
|
|
47
|
+
💥 Validation failed. Critical circular dependencies detected.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### How to Refactor Based on the Log Above:
|
|
51
|
+
|
|
52
|
+
The log indicates that `/packages/rest/src/init/rest.module.ts` contains an immediate top-level expression (such as an active decorator evaluation or configuration factory instantiation) that forces the evaluation of `routes.extension.ts` before the module evaluation of `rest.module.ts` is complete. To fix this, extract the shared configuration metadata or decorator targets into a dedicated initialization file positioned lower in the dependency hierarchy.
|
|
53
|
+
|
|
54
|
+
## Exit Codes
|
|
55
|
+
|
|
56
|
+
* `0`: Success. Clean graph or only safe, runtime-deferred cyclic references found.
|
|
57
|
+
* `1`: Critical Top-level execution loops found. Build terminated.
|
|
6
58
|
|
|
7
59
|
## Why Use This Over Existing Solutions?
|
|
8
60
|
|
|
@@ -15,15 +67,13 @@ In large-scale TypeScript applications (especially those utilizing Dependency In
|
|
|
15
67
|
|
|
16
68
|
### Technical Differentiators
|
|
17
69
|
|
|
18
|
-
| Feature | @ts-
|
|
70
|
+
| Feature | @ts-stack/cycle-detector | Traditional Tools (e.g., Madge) | ESLint Rules |
|
|
19
71
|
| --- | --- | --- | --- |
|
|
20
72
|
| **Analysis Scope** | Execution-aware (Top-level vs. Lazy) | Pure Import Graph Topology | Token-based / File Boundary |
|
|
21
73
|
| **TypeScript Engine** | Native `typescript` Compiler API | Pre-bundled bundlers / Regex | AST Walkers (without Full Type Context) |
|
|
22
74
|
| **Monorepo Mapping** | Dynamic `package.json` -> `src` tracking | Requires complex path mapping config | Scoped only to single-package roots |
|
|
23
75
|
| **Signal-to-Noise Ratio** | High (Flags only breaking cycles) | Low (Floods with safe runtime loops) | High overhead / Slow parsing |
|
|
24
76
|
|
|
25
|
-
---
|
|
26
|
-
|
|
27
77
|
## Core Architecture & Technical Details
|
|
28
78
|
|
|
29
79
|
### 1. Execution-Scoped Risk Assessment
|
|
@@ -43,8 +93,6 @@ In monorepos, internal package dependencies often resolve to `node_modules/<loca
|
|
|
43
93
|
|
|
44
94
|
To prevent log flooding from deeply nested structural loops, the DFS (Depth-First Search) cycle collector normalizes all found paths into a canonical key based on lexicographical rotation. You see each unique cycle exactly once, regardless of which file initiated the traversal.
|
|
45
95
|
|
|
46
|
-
---
|
|
47
|
-
|
|
48
96
|
## How It Works Under the Hood
|
|
49
97
|
|
|
50
98
|
```
|
|
@@ -55,53 +103,3 @@ To prevent log flooding from deeply nested structural loops, the DFS (Depth-Firs
|
|
|
55
103
|
2. **Phase 2: Graph Traversal:** Runs a non-recursive path collector detecting back-edges.
|
|
56
104
|
3. **Phase 3: Scope Validation:** For every edge in a detected cycle, it inspects whether the consumer node executes the imported token outside an execution-deferred scope block.
|
|
57
105
|
4. **Phase 4: Targeted Diagnostics:** Groups and outputs anomalies based on the entry point package context.
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## Installation & Usage
|
|
62
|
-
|
|
63
|
-
No configuration files are required. The script extracts metadata directly from your local environment.
|
|
64
|
-
|
|
65
|
-
### Execution
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
npx @ts-stack/cycle-detector <entry-patterns> [options]
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Arguments & Flags
|
|
72
|
-
|
|
73
|
-
* `<entry-patterns>`: Glob patterns or paths to entry point files (e.g., `packages/*/src/index.ts`).
|
|
74
|
-
* `-p, --project <path>`: Path to your root or fallback `tsconfig.json`.
|
|
75
|
-
|
|
76
|
-
### Example Command
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
npx @ts-stack/cycle-detector packages/*/src/index.ts
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## Interpreting Diagnostics
|
|
85
|
-
|
|
86
|
-
When a breaking circular dependency is detected, the script identifies exactly **which file executes the token prematurely**, leaving non-blocking files clearly marked.
|
|
87
|
-
|
|
88
|
-
```txt
|
|
89
|
-
❌ [/packages/rest/src/index.ts] — Found 1 critical circular dependencies:
|
|
90
|
-
1) --------------------------------------------------------------------------------
|
|
91
|
-
⏳ [Lazy] /srv/git/ditsmod/ditsmod/packages/rest/src/extensions/routes.extension.ts
|
|
92
|
-
⏳ [Lazy] /srv/git/ditsmod/ditsmod/packages/rest/src/decorators/rest-init-hooks-and-metadata.ts
|
|
93
|
-
💥 [Top-level] /srv/git/ditsmod/ditsmod/packages/rest/src/init/rest.module.ts
|
|
94
|
-
|
|
95
|
-
💥 Validation failed. Critical circular dependencies detected.
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### How to Refactor Based on the Log Above:
|
|
99
|
-
|
|
100
|
-
The log indicates that `/packages/rest/src/init/rest.module.ts` contains an immediate top-level expression (such as an active decorator evaluation or configuration factory instantiation) that forces the evaluation of `routes.extension.ts` before the module evaluation of `rest.module.ts` is complete. To fix this, extract the shared configuration metadata or decorator targets into a dedicated initialization file positioned lower in the dependency hierarchy.
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
## Exit Codes
|
|
105
|
-
|
|
106
|
-
* `0`: Success. Clean graph or only safe, runtime-deferred cyclic references found.
|
|
107
|
-
* `1`: Critical Top-level execution loops found. Build terminated.
|