@eldrforge/tree-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.
- package/LICENSE +22 -0
- package/README.md +92 -0
- package/dist/dependencyGraph.d.ts +54 -0
- package/dist/dependencyGraph.d.ts.map +1 -0
- package/dist/dependencyGraph.js +306 -0
- package/dist/dependencyGraph.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +32 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Calen Varek
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# @eldrforge/tree-core
|
|
2
|
+
|
|
3
|
+
Dependency graph algorithms for monorepo package analysis.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 📦 **Package Discovery** - Scan workspace for package.json files
|
|
8
|
+
- 🔍 **Dependency Analysis** - Build dependency graphs
|
|
9
|
+
- 📊 **Topological Sort** - Determine build order
|
|
10
|
+
- ⚠️ **Circular Detection** - Identify circular dependencies
|
|
11
|
+
- 🎯 **Pattern Filtering** - Exclude packages by pattern
|
|
12
|
+
- 💾 **Serialization** - Save/load graphs for checkpointing
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @eldrforge/tree-core
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import {
|
|
24
|
+
scanForPackageJsonFiles,
|
|
25
|
+
buildDependencyGraph,
|
|
26
|
+
topologicalSort
|
|
27
|
+
} from '@eldrforge/tree-core';
|
|
28
|
+
|
|
29
|
+
// Scan workspace for packages
|
|
30
|
+
const packagePaths = await scanForPackageJsonFiles('/path/to/workspace');
|
|
31
|
+
|
|
32
|
+
// Build dependency graph
|
|
33
|
+
const graph = await buildDependencyGraph(packagePaths);
|
|
34
|
+
|
|
35
|
+
// Get build order
|
|
36
|
+
const buildOrder = topologicalSort(graph);
|
|
37
|
+
|
|
38
|
+
console.log('Build order:', buildOrder);
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## API
|
|
42
|
+
|
|
43
|
+
### Package Discovery
|
|
44
|
+
|
|
45
|
+
- `scanForPackageJsonFiles(directory, excludedPatterns?)` - Find all package.json files
|
|
46
|
+
- `parsePackageJson(packageJsonPath)` - Parse and validate a package.json
|
|
47
|
+
- `shouldExclude(packagePath, excludedPatterns)` - Check if package should be excluded
|
|
48
|
+
|
|
49
|
+
### Graph Building
|
|
50
|
+
|
|
51
|
+
- `buildDependencyGraph(packageJsonPaths)` - Build dependency graph from packages
|
|
52
|
+
- `buildReverseGraph(edges)` - Create reverse dependency map
|
|
53
|
+
|
|
54
|
+
### Graph Analysis
|
|
55
|
+
|
|
56
|
+
- `topologicalSort(graph)` - Determine execution order
|
|
57
|
+
- `findAllDependents(packageName, graph)` - Find all packages that depend on a package
|
|
58
|
+
- `validateGraph(graph)` - Check graph integrity
|
|
59
|
+
|
|
60
|
+
### Serialization
|
|
61
|
+
|
|
62
|
+
- `serializeGraph(graph)` - Convert graph to JSON-serializable format
|
|
63
|
+
- `deserializeGraph(serialized)` - Restore graph from serialized format
|
|
64
|
+
|
|
65
|
+
## Types
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
interface PackageInfo {
|
|
69
|
+
name: string;
|
|
70
|
+
version: string;
|
|
71
|
+
path: string;
|
|
72
|
+
dependencies: Set<string>;
|
|
73
|
+
devDependencies: Set<string>;
|
|
74
|
+
localDependencies: Set<string>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
interface DependencyGraph {
|
|
78
|
+
packages: Map<string, PackageInfo>;
|
|
79
|
+
edges: Map<string, Set<string>>;
|
|
80
|
+
reverseEdges: Map<string, Set<string>>;
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Dependencies
|
|
85
|
+
|
|
86
|
+
- `@eldrforge/git-tools` - Git operations and validation
|
|
87
|
+
- `@eldrforge/shared` - Shared utilities
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
MIT © Calen Varek
|
|
92
|
+
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { PackageInfo, DependencyGraph, SerializedGraph } from './types.js';
|
|
2
|
+
interface Logger {
|
|
3
|
+
info(message: string, ...args: any[]): void;
|
|
4
|
+
error(message: string, ...args: any[]): void;
|
|
5
|
+
warn(message: string, ...args: any[]): void;
|
|
6
|
+
verbose(message: string, ...args: any[]): void;
|
|
7
|
+
debug(message: string, ...args: any[]): void;
|
|
8
|
+
}
|
|
9
|
+
export declare function setLogger(newLogger: Logger): void;
|
|
10
|
+
/**
|
|
11
|
+
* Check if a package should be excluded based on patterns
|
|
12
|
+
*/
|
|
13
|
+
export declare function shouldExclude(packageJsonPath: string, excludedPatterns: string[]): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Scan directory for package.json files
|
|
16
|
+
*/
|
|
17
|
+
export declare function scanForPackageJsonFiles(directory: string, excludedPatterns?: string[]): Promise<string[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Parse a single package.json file
|
|
20
|
+
*/
|
|
21
|
+
export declare function parsePackageJson(packageJsonPath: string): Promise<PackageInfo>;
|
|
22
|
+
/**
|
|
23
|
+
* Build dependency graph from package.json paths
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildDependencyGraph(packageJsonPaths: string[]): Promise<DependencyGraph>;
|
|
26
|
+
/**
|
|
27
|
+
* Build reverse dependency graph (package -> dependents)
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildReverseGraph(edges: Map<string, Set<string>>): Map<string, Set<string>>;
|
|
30
|
+
/**
|
|
31
|
+
* Perform topological sort on dependency graph
|
|
32
|
+
*/
|
|
33
|
+
export declare function topologicalSort(graph: DependencyGraph): string[];
|
|
34
|
+
/**
|
|
35
|
+
* Find all dependents of a package (packages that depend on it)
|
|
36
|
+
*/
|
|
37
|
+
export declare function findAllDependents(packageName: string, graph: DependencyGraph): Set<string>;
|
|
38
|
+
/**
|
|
39
|
+
* Serialize graph for checkpoint persistence
|
|
40
|
+
*/
|
|
41
|
+
export declare function serializeGraph(graph: DependencyGraph): SerializedGraph;
|
|
42
|
+
/**
|
|
43
|
+
* Deserialize graph from checkpoint
|
|
44
|
+
*/
|
|
45
|
+
export declare function deserializeGraph(serialized: SerializedGraph): DependencyGraph;
|
|
46
|
+
/**
|
|
47
|
+
* Validate graph integrity
|
|
48
|
+
*/
|
|
49
|
+
export declare function validateGraph(graph: DependencyGraph): {
|
|
50
|
+
valid: boolean;
|
|
51
|
+
errors: string[];
|
|
52
|
+
};
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=dependencyGraph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencyGraph.d.ts","sourceRoot":"","sources":["../src/dependencyGraph.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGhF,UAAU,MAAM;IACZ,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC7C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC5C,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;CAChD;AAUD,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEjD;AAsBD;;GAEG;AACH,wBAAgB,aAAa,CAAC,eAAe,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,GAAG,OAAO,CAc1F;AAID;;GAEG;AACH,wBAAsB,uBAAuB,CACzC,SAAS,EAAE,MAAM,EACjB,gBAAgB,GAAE,MAAM,EAAO,GAChC,OAAO,CAAC,MAAM,EAAE,CAAC,CAmDnB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAyCpF;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACtC,gBAAgB,EAAE,MAAM,EAAE,GAC3B,OAAO,CAAC,eAAe,CAAC,CAiC1B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC7B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GAChC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAa1B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,EAAE,CAsChE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC7B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,eAAe,GACvB,GAAG,CAAC,MAAM,CAAC,CAiBb;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe,CAatE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,eAAe,GAAG,eAAe,CAyB7E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,eAAe,GAAG;IACnD,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CACpB,CAuBA"}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import { safeJsonParse, validatePackageJson } from '@eldrforge/git-tools';
|
|
4
|
+
import { createStorage } from '@eldrforge/shared';
|
|
5
|
+
let logger = {
|
|
6
|
+
info: () => { },
|
|
7
|
+
error: (...args) => console.error(...args),
|
|
8
|
+
warn: (...args) => console.warn(...args),
|
|
9
|
+
verbose: () => { },
|
|
10
|
+
debug: () => { }
|
|
11
|
+
};
|
|
12
|
+
export function setLogger(newLogger) {
|
|
13
|
+
logger = newLogger;
|
|
14
|
+
}
|
|
15
|
+
function getLogger() {
|
|
16
|
+
return logger;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Check if a file path matches a glob pattern
|
|
20
|
+
*/
|
|
21
|
+
const matchesPattern = (filePath, pattern) => {
|
|
22
|
+
// Convert simple glob patterns to regex
|
|
23
|
+
const regexPattern = pattern
|
|
24
|
+
.replace(/\\/g, '\\\\') // Escape backslashes
|
|
25
|
+
.replace(/\*\*/g, '.*') // ** matches any path segments
|
|
26
|
+
.replace(/\*/g, '[^/]*') // * matches any characters except path separator
|
|
27
|
+
.replace(/\?/g, '.') // ? matches any single character
|
|
28
|
+
.replace(/\./g, '\\.'); // Escape literal dots
|
|
29
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
30
|
+
return regex.test(filePath) || regex.test(path.basename(filePath));
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Check if a package should be excluded based on patterns
|
|
34
|
+
*/
|
|
35
|
+
export function shouldExclude(packageJsonPath, excludedPatterns) {
|
|
36
|
+
if (!excludedPatterns || excludedPatterns.length === 0) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
// Check both the full path and relative path patterns
|
|
40
|
+
const relativePath = path.relative(process.cwd(), packageJsonPath);
|
|
41
|
+
return excludedPatterns.some(pattern => matchesPattern(packageJsonPath, pattern) ||
|
|
42
|
+
matchesPattern(relativePath, pattern) ||
|
|
43
|
+
matchesPattern(path.dirname(packageJsonPath), pattern) ||
|
|
44
|
+
matchesPattern(path.dirname(relativePath), pattern));
|
|
45
|
+
}
|
|
46
|
+
// Types are now imported from types.ts
|
|
47
|
+
/**
|
|
48
|
+
* Scan directory for package.json files
|
|
49
|
+
*/
|
|
50
|
+
export async function scanForPackageJsonFiles(directory, excludedPatterns = []) {
|
|
51
|
+
const logger = getLogger();
|
|
52
|
+
const packageJsonPaths = [];
|
|
53
|
+
try {
|
|
54
|
+
// First check if there's a package.json in the specified directory itself
|
|
55
|
+
const directPackageJsonPath = path.join(directory, 'package.json');
|
|
56
|
+
try {
|
|
57
|
+
await fs.access(directPackageJsonPath);
|
|
58
|
+
// Check if this package should be excluded
|
|
59
|
+
if (!shouldExclude(directPackageJsonPath, excludedPatterns)) {
|
|
60
|
+
packageJsonPaths.push(directPackageJsonPath);
|
|
61
|
+
logger.verbose(`Found package.json at: ${directPackageJsonPath}`);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
logger.verbose(`Excluding package.json at: ${directPackageJsonPath} (matches exclusion pattern)`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// No package.json in the root of this directory, that's fine
|
|
69
|
+
}
|
|
70
|
+
// Then scan subdirectories for package.json files
|
|
71
|
+
const entries = await fs.readdir(directory, { withFileTypes: true });
|
|
72
|
+
for (const entry of entries) {
|
|
73
|
+
if (entry.isDirectory()) {
|
|
74
|
+
const subDirPath = path.join(directory, entry.name);
|
|
75
|
+
const packageJsonPath = path.join(subDirPath, 'package.json');
|
|
76
|
+
try {
|
|
77
|
+
await fs.access(packageJsonPath);
|
|
78
|
+
// Check if this package should be excluded
|
|
79
|
+
if (shouldExclude(packageJsonPath, excludedPatterns)) {
|
|
80
|
+
logger.verbose(`Excluding package.json at: ${packageJsonPath} (matches exclusion pattern)`);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
packageJsonPaths.push(packageJsonPath);
|
|
84
|
+
logger.verbose(`Found package.json at: ${packageJsonPath}`);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// No package.json in this directory, continue
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
logger.error(`DEPENDENCY_GRAPH_SCAN_FAILED: Failed to scan directory | Directory: ${directory} | Error: ${error}`);
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
return packageJsonPaths;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Parse a single package.json file
|
|
100
|
+
*/
|
|
101
|
+
export async function parsePackageJson(packageJsonPath) {
|
|
102
|
+
const logger = getLogger();
|
|
103
|
+
const storage = createStorage();
|
|
104
|
+
try {
|
|
105
|
+
const content = await storage.readFile(packageJsonPath, 'utf-8');
|
|
106
|
+
const parsed = safeJsonParse(content, packageJsonPath);
|
|
107
|
+
const packageJson = validatePackageJson(parsed, packageJsonPath);
|
|
108
|
+
if (!packageJson.name) {
|
|
109
|
+
throw new Error(`Package at ${packageJsonPath} has no name field`);
|
|
110
|
+
}
|
|
111
|
+
const dependencies = new Set();
|
|
112
|
+
const devDependencies = new Set();
|
|
113
|
+
// Collect all types of dependencies
|
|
114
|
+
const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
|
|
115
|
+
for (const depType of depTypes) {
|
|
116
|
+
if (packageJson[depType]) {
|
|
117
|
+
Object.keys(packageJson[depType]).forEach(dep => {
|
|
118
|
+
dependencies.add(dep);
|
|
119
|
+
if (depType === 'devDependencies') {
|
|
120
|
+
devDependencies.add(dep);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
name: packageJson.name,
|
|
127
|
+
version: packageJson.version || '0.0.0',
|
|
128
|
+
path: path.dirname(packageJsonPath),
|
|
129
|
+
dependencies,
|
|
130
|
+
devDependencies,
|
|
131
|
+
localDependencies: new Set() // Will be populated later
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
logger.error(`DEPENDENCY_GRAPH_PARSE_FAILED: Failed to parse package.json | Path: ${packageJsonPath} | Error: ${error}`);
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Build dependency graph from package.json paths
|
|
141
|
+
*/
|
|
142
|
+
export async function buildDependencyGraph(packageJsonPaths) {
|
|
143
|
+
const logger = getLogger();
|
|
144
|
+
const packages = new Map();
|
|
145
|
+
const edges = new Map();
|
|
146
|
+
// First pass: parse all package.json files
|
|
147
|
+
for (const packageJsonPath of packageJsonPaths) {
|
|
148
|
+
const packageInfo = await parsePackageJson(packageJsonPath);
|
|
149
|
+
packages.set(packageInfo.name, packageInfo);
|
|
150
|
+
logger.verbose(`Parsed package: ${packageInfo.name} at ${packageInfo.path}`);
|
|
151
|
+
}
|
|
152
|
+
// Second pass: identify local dependencies and build edges
|
|
153
|
+
for (const [packageName, packageInfo] of packages) {
|
|
154
|
+
const localDeps = new Set();
|
|
155
|
+
const edgesSet = new Set();
|
|
156
|
+
for (const dep of packageInfo.dependencies) {
|
|
157
|
+
if (packages.has(dep)) {
|
|
158
|
+
localDeps.add(dep);
|
|
159
|
+
edgesSet.add(dep);
|
|
160
|
+
logger.verbose(`${packageName} depends on local package: ${dep}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
packageInfo.localDependencies = localDeps;
|
|
164
|
+
edges.set(packageName, edgesSet);
|
|
165
|
+
}
|
|
166
|
+
// Build reverse edges (dependents)
|
|
167
|
+
const reverseEdges = buildReverseGraph(edges);
|
|
168
|
+
return { packages, edges, reverseEdges };
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Build reverse dependency graph (package -> dependents)
|
|
172
|
+
*/
|
|
173
|
+
export function buildReverseGraph(edges) {
|
|
174
|
+
const reverse = new Map();
|
|
175
|
+
for (const [pkg, deps] of edges) {
|
|
176
|
+
for (const dep of deps) {
|
|
177
|
+
if (!reverse.has(dep)) {
|
|
178
|
+
reverse.set(dep, new Set());
|
|
179
|
+
}
|
|
180
|
+
reverse.get(dep).add(pkg);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return reverse;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Perform topological sort on dependency graph
|
|
187
|
+
*/
|
|
188
|
+
export function topologicalSort(graph) {
|
|
189
|
+
const logger = getLogger();
|
|
190
|
+
const { packages, edges } = graph;
|
|
191
|
+
const visited = new Set();
|
|
192
|
+
const visiting = new Set();
|
|
193
|
+
const result = [];
|
|
194
|
+
const visit = (packageName) => {
|
|
195
|
+
if (visited.has(packageName)) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (visiting.has(packageName)) {
|
|
199
|
+
throw new Error(`Circular dependency detected involving package: ${packageName}`);
|
|
200
|
+
}
|
|
201
|
+
visiting.add(packageName);
|
|
202
|
+
// Visit all dependencies first
|
|
203
|
+
const deps = edges.get(packageName) || new Set();
|
|
204
|
+
for (const dep of deps) {
|
|
205
|
+
visit(dep);
|
|
206
|
+
}
|
|
207
|
+
visiting.delete(packageName);
|
|
208
|
+
visited.add(packageName);
|
|
209
|
+
result.push(packageName);
|
|
210
|
+
};
|
|
211
|
+
// Visit all packages
|
|
212
|
+
for (const packageName of packages.keys()) {
|
|
213
|
+
if (!visited.has(packageName)) {
|
|
214
|
+
visit(packageName);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
logger.verbose(`Topological sort completed. Build order determined for ${result.length} packages.`);
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Find all dependents of a package (packages that depend on it)
|
|
222
|
+
*/
|
|
223
|
+
export function findAllDependents(packageName, graph) {
|
|
224
|
+
const dependents = new Set();
|
|
225
|
+
const visited = new Set();
|
|
226
|
+
const traverse = (pkg) => {
|
|
227
|
+
if (visited.has(pkg))
|
|
228
|
+
return;
|
|
229
|
+
visited.add(pkg);
|
|
230
|
+
const directDependents = graph.reverseEdges.get(pkg) || new Set();
|
|
231
|
+
for (const dependent of directDependents) {
|
|
232
|
+
dependents.add(dependent);
|
|
233
|
+
traverse(dependent);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
traverse(packageName);
|
|
237
|
+
return dependents;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Serialize graph for checkpoint persistence
|
|
241
|
+
*/
|
|
242
|
+
export function serializeGraph(graph) {
|
|
243
|
+
return {
|
|
244
|
+
packages: Array.from(graph.packages.values()).map(pkg => ({
|
|
245
|
+
name: pkg.name,
|
|
246
|
+
version: pkg.version,
|
|
247
|
+
path: pkg.path,
|
|
248
|
+
dependencies: Array.from(pkg.dependencies)
|
|
249
|
+
})),
|
|
250
|
+
edges: Array.from(graph.edges.entries()).map(([pkg, deps]) => [
|
|
251
|
+
pkg,
|
|
252
|
+
Array.from(deps)
|
|
253
|
+
])
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Deserialize graph from checkpoint
|
|
258
|
+
*/
|
|
259
|
+
export function deserializeGraph(serialized) {
|
|
260
|
+
const packages = new Map();
|
|
261
|
+
const edges = new Map();
|
|
262
|
+
// Restore packages
|
|
263
|
+
for (const pkg of serialized.packages) {
|
|
264
|
+
packages.set(pkg.name, {
|
|
265
|
+
name: pkg.name,
|
|
266
|
+
version: pkg.version,
|
|
267
|
+
path: pkg.path,
|
|
268
|
+
dependencies: new Set(pkg.dependencies),
|
|
269
|
+
devDependencies: new Set(),
|
|
270
|
+
localDependencies: new Set()
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
// Restore edges
|
|
274
|
+
for (const [pkg, deps] of serialized.edges) {
|
|
275
|
+
edges.set(pkg, new Set(deps));
|
|
276
|
+
}
|
|
277
|
+
// Build reverse edges
|
|
278
|
+
const reverseEdges = buildReverseGraph(edges);
|
|
279
|
+
return { packages, edges, reverseEdges };
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Validate graph integrity
|
|
283
|
+
*/
|
|
284
|
+
export function validateGraph(graph) {
|
|
285
|
+
const errors = [];
|
|
286
|
+
// Check all edge targets exist
|
|
287
|
+
for (const [pkg, deps] of graph.edges) {
|
|
288
|
+
for (const dep of deps) {
|
|
289
|
+
if (!graph.packages.has(dep)) {
|
|
290
|
+
errors.push(`Package ${pkg} depends on ${dep} which doesn't exist`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// Check for circular dependencies
|
|
295
|
+
try {
|
|
296
|
+
topologicalSort(graph);
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
errors.push(error.message);
|
|
300
|
+
}
|
|
301
|
+
return {
|
|
302
|
+
valid: errors.length === 0,
|
|
303
|
+
errors
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=dependencyGraph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencyGraph.js","sourceRoot":"","sources":["../src/dependencyGraph.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @eldrforge/tree-core
|
|
3
|
+
*
|
|
4
|
+
* Dependency graph algorithms for monorepo package analysis.
|
|
5
|
+
*/
|
|
6
|
+
export type { PackageInfo, DependencyGraph, SerializedGraph } from './types.js';
|
|
7
|
+
export { scanForPackageJsonFiles, parsePackageJson, shouldExclude } from './dependencyGraph.js';
|
|
8
|
+
export { buildDependencyGraph, buildReverseGraph } from './dependencyGraph.js';
|
|
9
|
+
export { topologicalSort, findAllDependents, validateGraph } from './dependencyGraph.js';
|
|
10
|
+
export { serializeGraph, deserializeGraph } from './dependencyGraph.js';
|
|
11
|
+
export { setLogger } from './dependencyGraph.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGhF,OAAO,EACH,uBAAuB,EACvB,gBAAgB,EAChB,aAAa,EAChB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACH,oBAAoB,EACpB,iBAAiB,EACpB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,aAAa,EAChB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACH,cAAc,EACd,gBAAgB,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @eldrforge/tree-core
|
|
3
|
+
*
|
|
4
|
+
* Dependency graph algorithms for monorepo package analysis.
|
|
5
|
+
*/
|
|
6
|
+
// Package discovery
|
|
7
|
+
export { scanForPackageJsonFiles, parsePackageJson, shouldExclude } from './dependencyGraph.js';
|
|
8
|
+
// Graph building
|
|
9
|
+
export { buildDependencyGraph, buildReverseGraph } from './dependencyGraph.js';
|
|
10
|
+
// Graph analysis
|
|
11
|
+
export { topologicalSort, findAllDependents, validateGraph } from './dependencyGraph.js';
|
|
12
|
+
// Serialization
|
|
13
|
+
export { serializeGraph, deserializeGraph } from './dependencyGraph.js';
|
|
14
|
+
// Logger configuration
|
|
15
|
+
export { setLogger } from './dependencyGraph.js';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,oBAAoB;AACpB,OAAO,EACH,uBAAuB,EACvB,gBAAgB,EAChB,aAAa,EAChB,MAAM,sBAAsB,CAAC;AAE9B,iBAAiB;AACjB,OAAO,EACH,oBAAoB,EACpB,iBAAiB,EACpB,MAAM,sBAAsB,CAAC;AAE9B,iBAAiB;AACjB,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,aAAa,EAChB,MAAM,sBAAsB,CAAC;AAE9B,gBAAgB;AAChB,OAAO,EACH,cAAc,EACd,gBAAgB,EACnB,MAAM,sBAAsB,CAAC;AAE9B,uBAAuB;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Information about a single package
|
|
3
|
+
*/
|
|
4
|
+
export interface PackageInfo {
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
path: string;
|
|
8
|
+
dependencies: Set<string>;
|
|
9
|
+
devDependencies: Set<string>;
|
|
10
|
+
localDependencies: Set<string>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Dependency graph structure
|
|
14
|
+
*/
|
|
15
|
+
export interface DependencyGraph {
|
|
16
|
+
packages: Map<string, PackageInfo>;
|
|
17
|
+
edges: Map<string, Set<string>>;
|
|
18
|
+
reverseEdges: Map<string, Set<string>>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Serialized graph for checkpointing
|
|
22
|
+
*/
|
|
23
|
+
export interface SerializedGraph {
|
|
24
|
+
packages: Array<{
|
|
25
|
+
name: string;
|
|
26
|
+
version: string;
|
|
27
|
+
path: string;
|
|
28
|
+
dependencies: string[];
|
|
29
|
+
}>;
|
|
30
|
+
edges: Array<[string, string[]]>;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACnC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAChC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC,CAAC;IACH,KAAK,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;CACpC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@eldrforge/tree-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Dependency graph algorithms for monorepo package analysis",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"test": "vitest run",
|
|
11
|
+
"test:watch": "vitest",
|
|
12
|
+
"test:coverage": "vitest run --coverage",
|
|
13
|
+
"lint": "eslint src tests --ext .ts",
|
|
14
|
+
"clean": "rm -rf dist coverage",
|
|
15
|
+
"prepublishOnly": "npm run clean && npm run build && npm test"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"dependency-graph",
|
|
19
|
+
"monorepo",
|
|
20
|
+
"package-analysis",
|
|
21
|
+
"topological-sort",
|
|
22
|
+
"dependency-resolution"
|
|
23
|
+
],
|
|
24
|
+
"author": "Calen Varek <calenvarek@gmail.com>",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/calenvarek/tree-core.git"
|
|
29
|
+
},
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/calenvarek/tree-core/issues"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/calenvarek/tree-core#readme",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@eldrforge/git-tools": "^0.1.6",
|
|
36
|
+
"@eldrforge/shared": "^0.1.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^22.10.2",
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^8.18.1",
|
|
41
|
+
"@typescript-eslint/parser": "^8.18.1",
|
|
42
|
+
"@vitest/coverage-v8": "^2.1.8",
|
|
43
|
+
"eslint": "^9.17.0",
|
|
44
|
+
"typescript": "^5.7.2",
|
|
45
|
+
"vitest": "^2.1.8"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18.0.0"
|
|
49
|
+
},
|
|
50
|
+
"files": [
|
|
51
|
+
"dist",
|
|
52
|
+
"README.md",
|
|
53
|
+
"LICENSE"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
|