@webpieces/dev-config 0.2.17 → 0.2.21
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/architecture/executors/generate/executor.d.ts +17 -0
- package/architecture/executors/generate/executor.js +67 -0
- package/architecture/executors/generate/executor.js.map +1 -0
- package/architecture/executors/generate/executor.ts +83 -0
- package/architecture/executors/generate/schema.json +14 -0
- package/architecture/executors/validate-architecture-unchanged/executor.d.ts +17 -0
- package/architecture/executors/validate-architecture-unchanged/executor.js +65 -0
- package/architecture/executors/validate-architecture-unchanged/executor.js.map +1 -0
- package/architecture/executors/validate-architecture-unchanged/executor.ts +81 -0
- package/architecture/executors/validate-architecture-unchanged/schema.json +14 -0
- package/architecture/executors/validate-no-cycles/executor.d.ts +16 -0
- package/architecture/executors/validate-no-cycles/executor.js +48 -0
- package/architecture/executors/validate-no-cycles/executor.js.map +1 -0
- package/architecture/executors/validate-no-cycles/executor.ts +60 -0
- package/architecture/executors/validate-no-cycles/schema.json +8 -0
- package/architecture/executors/validate-no-skiplevel-deps/executor.d.ts +19 -0
- package/architecture/executors/validate-no-skiplevel-deps/executor.js +227 -0
- package/architecture/executors/validate-no-skiplevel-deps/executor.js.map +1 -0
- package/architecture/executors/validate-no-skiplevel-deps/executor.ts +267 -0
- package/architecture/executors/validate-no-skiplevel-deps/schema.json +8 -0
- package/architecture/executors/visualize/executor.d.ts +17 -0
- package/architecture/executors/visualize/executor.js +49 -0
- package/architecture/executors/visualize/executor.js.map +1 -0
- package/architecture/executors/visualize/executor.ts +63 -0
- package/architecture/executors/visualize/schema.json +14 -0
- package/architecture/index.d.ts +19 -0
- package/architecture/index.js +23 -0
- package/architecture/index.js.map +1 -0
- package/architecture/index.ts +20 -0
- package/architecture/lib/graph-comparator.d.ts +39 -0
- package/architecture/lib/graph-comparator.js +100 -0
- package/architecture/lib/graph-comparator.js.map +1 -0
- package/architecture/lib/graph-comparator.ts +141 -0
- package/architecture/lib/graph-generator.d.ts +19 -0
- package/architecture/lib/graph-generator.js +88 -0
- package/architecture/lib/graph-generator.js.map +1 -0
- package/architecture/lib/graph-generator.ts +102 -0
- package/architecture/lib/graph-loader.d.ts +31 -0
- package/architecture/lib/graph-loader.js +70 -0
- package/architecture/lib/graph-loader.js.map +1 -0
- package/architecture/lib/graph-loader.ts +82 -0
- package/architecture/lib/graph-sorter.d.ts +37 -0
- package/architecture/lib/graph-sorter.js +110 -0
- package/architecture/lib/graph-sorter.js.map +1 -0
- package/architecture/lib/graph-sorter.ts +137 -0
- package/architecture/lib/graph-visualizer.d.ts +29 -0
- package/architecture/lib/graph-visualizer.js +209 -0
- package/architecture/lib/graph-visualizer.js.map +1 -0
- package/architecture/lib/graph-visualizer.ts +222 -0
- package/architecture/lib/package-validator.d.ts +38 -0
- package/architecture/lib/package-validator.js +105 -0
- package/architecture/lib/package-validator.js.map +1 -0
- package/architecture/lib/package-validator.ts +144 -0
- package/config/eslint/base.mjs +6 -0
- package/eslint-plugin/__tests__/max-file-lines.test.ts +207 -0
- package/eslint-plugin/__tests__/max-method-lines.test.ts +258 -0
- package/eslint-plugin/__tests__/no-unmanaged-exceptions.test.ts +359 -0
- package/eslint-plugin/index.d.ts +11 -0
- package/eslint-plugin/index.js +15 -0
- package/eslint-plugin/index.js.map +1 -1
- package/eslint-plugin/index.ts +15 -0
- package/eslint-plugin/rules/enforce-architecture.d.ts +15 -0
- package/eslint-plugin/rules/enforce-architecture.js +406 -0
- package/eslint-plugin/rules/enforce-architecture.js.map +1 -0
- package/eslint-plugin/rules/enforce-architecture.ts +469 -0
- package/eslint-plugin/rules/max-file-lines.d.ts +12 -0
- package/eslint-plugin/rules/max-file-lines.js +257 -0
- package/eslint-plugin/rules/max-file-lines.js.map +1 -0
- package/eslint-plugin/rules/max-file-lines.ts +272 -0
- package/eslint-plugin/rules/max-method-lines.d.ts +12 -0
- package/eslint-plugin/rules/max-method-lines.js +240 -0
- package/eslint-plugin/rules/max-method-lines.js.map +1 -0
- package/eslint-plugin/rules/max-method-lines.ts +287 -0
- package/eslint-plugin/rules/no-unmanaged-exceptions.d.ts +22 -0
- package/eslint-plugin/rules/no-unmanaged-exceptions.js +605 -0
- package/eslint-plugin/rules/no-unmanaged-exceptions.js.map +1 -0
- package/eslint-plugin/rules/no-unmanaged-exceptions.ts +621 -0
- package/executors.json +29 -0
- package/package.json +13 -3
- package/plugins/circular-deps/index.d.ts +8 -0
- package/plugins/circular-deps/index.js +14 -0
- package/plugins/circular-deps/index.js.map +1 -0
- package/plugins/circular-deps/index.ts +9 -0
- package/plugins/circular-deps/plugin.d.ts +32 -0
- package/plugins/circular-deps/plugin.js +73 -0
- package/plugins/circular-deps/plugin.js.map +1 -0
- package/plugins/circular-deps/plugin.ts +83 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"title": "Visualize Executor",
|
|
4
|
+
"description": "Generates visual representations of the architecture graph",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"graphPath": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "Path to the graph file (relative to workspace root)",
|
|
10
|
+
"default": "architecture/dependencies.json"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"required": []
|
|
14
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architecture Validation Module
|
|
3
|
+
*
|
|
4
|
+
* Provides tools for validating and managing the architecture dependency graph.
|
|
5
|
+
*
|
|
6
|
+
* Exports:
|
|
7
|
+
* - Graph generation from project.json files
|
|
8
|
+
* - Topological sorting and cycle detection
|
|
9
|
+
* - Package.json validation
|
|
10
|
+
* - Graph comparison
|
|
11
|
+
* - Graph file loading/saving
|
|
12
|
+
* - Graph visualization (DOT + HTML)
|
|
13
|
+
*/
|
|
14
|
+
export * from './lib/graph-generator';
|
|
15
|
+
export * from './lib/graph-sorter';
|
|
16
|
+
export * from './lib/graph-comparator';
|
|
17
|
+
export * from './lib/package-validator';
|
|
18
|
+
export * from './lib/graph-loader';
|
|
19
|
+
export * from './lib/graph-visualizer';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Architecture Validation Module
|
|
4
|
+
*
|
|
5
|
+
* Provides tools for validating and managing the architecture dependency graph.
|
|
6
|
+
*
|
|
7
|
+
* Exports:
|
|
8
|
+
* - Graph generation from project.json files
|
|
9
|
+
* - Topological sorting and cycle detection
|
|
10
|
+
* - Package.json validation
|
|
11
|
+
* - Graph comparison
|
|
12
|
+
* - Graph file loading/saving
|
|
13
|
+
* - Graph visualization (DOT + HTML)
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
const tslib_1 = require("tslib");
|
|
17
|
+
tslib_1.__exportStar(require("./lib/graph-generator"), exports);
|
|
18
|
+
tslib_1.__exportStar(require("./lib/graph-sorter"), exports);
|
|
19
|
+
tslib_1.__exportStar(require("./lib/graph-comparator"), exports);
|
|
20
|
+
tslib_1.__exportStar(require("./lib/package-validator"), exports);
|
|
21
|
+
tslib_1.__exportStar(require("./lib/graph-loader"), exports);
|
|
22
|
+
tslib_1.__exportStar(require("./lib/graph-visualizer"), exports);
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/tooling/dev-config/architecture/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;AAEH,gEAAsC;AACtC,6DAAmC;AACnC,iEAAuC;AACvC,kEAAwC;AACxC,6DAAmC;AACnC,iEAAuC","sourcesContent":["/**\n * Architecture Validation Module\n *\n * Provides tools for validating and managing the architecture dependency graph.\n *\n * Exports:\n * - Graph generation from project.json files\n * - Topological sorting and cycle detection\n * - Package.json validation\n * - Graph comparison\n * - Graph file loading/saving\n * - Graph visualization (DOT + HTML)\n */\n\nexport * from './lib/graph-generator';\nexport * from './lib/graph-sorter';\nexport * from './lib/graph-comparator';\nexport * from './lib/package-validator';\nexport * from './lib/graph-loader';\nexport * from './lib/graph-visualizer';\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architecture Validation Module
|
|
3
|
+
*
|
|
4
|
+
* Provides tools for validating and managing the architecture dependency graph.
|
|
5
|
+
*
|
|
6
|
+
* Exports:
|
|
7
|
+
* - Graph generation from project.json files
|
|
8
|
+
* - Topological sorting and cycle detection
|
|
9
|
+
* - Package.json validation
|
|
10
|
+
* - Graph comparison
|
|
11
|
+
* - Graph file loading/saving
|
|
12
|
+
* - Graph visualization (DOT + HTML)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export * from './lib/graph-generator';
|
|
16
|
+
export * from './lib/graph-sorter';
|
|
17
|
+
export * from './lib/graph-comparator';
|
|
18
|
+
export * from './lib/package-validator';
|
|
19
|
+
export * from './lib/graph-loader';
|
|
20
|
+
export * from './lib/graph-visualizer';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph Comparator
|
|
3
|
+
*
|
|
4
|
+
* Compares the current generated graph with the saved (blessed) graph.
|
|
5
|
+
* Used in validate mode to ensure developers have updated the graph file.
|
|
6
|
+
*/
|
|
7
|
+
import type { EnhancedGraph } from './graph-sorter';
|
|
8
|
+
/**
|
|
9
|
+
* Difference between two graphs
|
|
10
|
+
*/
|
|
11
|
+
export interface GraphDiff {
|
|
12
|
+
added: string[];
|
|
13
|
+
removed: string[];
|
|
14
|
+
modified: {
|
|
15
|
+
project: string;
|
|
16
|
+
addedDeps: string[];
|
|
17
|
+
removedDeps: string[];
|
|
18
|
+
levelChanged: {
|
|
19
|
+
from: number;
|
|
20
|
+
to: number;
|
|
21
|
+
} | null;
|
|
22
|
+
}[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Comparison result
|
|
26
|
+
*/
|
|
27
|
+
export interface ComparisonResult {
|
|
28
|
+
identical: boolean;
|
|
29
|
+
diff: GraphDiff;
|
|
30
|
+
summary: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Compare two graphs and return the differences
|
|
34
|
+
*
|
|
35
|
+
* @param current - Currently generated graph
|
|
36
|
+
* @param saved - Previously saved (blessed) graph
|
|
37
|
+
* @returns Comparison result with detailed diff
|
|
38
|
+
*/
|
|
39
|
+
export declare function compareGraphs(current: EnhancedGraph, saved: EnhancedGraph): ComparisonResult;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Graph Comparator
|
|
4
|
+
*
|
|
5
|
+
* Compares the current generated graph with the saved (blessed) graph.
|
|
6
|
+
* Used in validate mode to ensure developers have updated the graph file.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.compareGraphs = compareGraphs;
|
|
10
|
+
/**
|
|
11
|
+
* Compare two graphs and return the differences
|
|
12
|
+
*
|
|
13
|
+
* @param current - Currently generated graph
|
|
14
|
+
* @param saved - Previously saved (blessed) graph
|
|
15
|
+
* @returns Comparison result with detailed diff
|
|
16
|
+
*/
|
|
17
|
+
function compareGraphs(current, saved) {
|
|
18
|
+
const currentProjects = new Set(Object.keys(current));
|
|
19
|
+
const savedProjects = new Set(Object.keys(saved));
|
|
20
|
+
const diff = {
|
|
21
|
+
added: [],
|
|
22
|
+
removed: [],
|
|
23
|
+
modified: [],
|
|
24
|
+
};
|
|
25
|
+
// Find added projects
|
|
26
|
+
for (const project of currentProjects) {
|
|
27
|
+
if (!savedProjects.has(project)) {
|
|
28
|
+
diff.added.push(project);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Find removed projects
|
|
32
|
+
for (const project of savedProjects) {
|
|
33
|
+
if (!currentProjects.has(project)) {
|
|
34
|
+
diff.removed.push(project);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Find modified projects
|
|
38
|
+
for (const project of currentProjects) {
|
|
39
|
+
if (!savedProjects.has(project))
|
|
40
|
+
continue;
|
|
41
|
+
const currentEntry = current[project];
|
|
42
|
+
const savedEntry = saved[project];
|
|
43
|
+
const currentDeps = new Set(currentEntry.dependsOn);
|
|
44
|
+
const savedDeps = new Set(savedEntry.dependsOn);
|
|
45
|
+
const addedDeps = [];
|
|
46
|
+
const removedDeps = [];
|
|
47
|
+
for (const dep of currentDeps) {
|
|
48
|
+
if (!savedDeps.has(dep)) {
|
|
49
|
+
addedDeps.push(dep);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
for (const dep of savedDeps) {
|
|
53
|
+
if (!currentDeps.has(dep)) {
|
|
54
|
+
removedDeps.push(dep);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const levelChanged = currentEntry.level !== savedEntry.level
|
|
58
|
+
? { from: savedEntry.level, to: currentEntry.level }
|
|
59
|
+
: null;
|
|
60
|
+
if (addedDeps.length > 0 || removedDeps.length > 0 || levelChanged) {
|
|
61
|
+
diff.modified.push({
|
|
62
|
+
project,
|
|
63
|
+
addedDeps,
|
|
64
|
+
removedDeps,
|
|
65
|
+
levelChanged,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const identical = diff.added.length === 0 && diff.removed.length === 0 && diff.modified.length === 0;
|
|
70
|
+
// Generate summary
|
|
71
|
+
const summaryParts = [];
|
|
72
|
+
if (diff.added.length > 0) {
|
|
73
|
+
summaryParts.push(`Added projects: ${diff.added.join(', ')}`);
|
|
74
|
+
}
|
|
75
|
+
if (diff.removed.length > 0) {
|
|
76
|
+
summaryParts.push(`Removed projects: ${diff.removed.join(', ')}`);
|
|
77
|
+
}
|
|
78
|
+
for (const mod of diff.modified) {
|
|
79
|
+
const parts = [];
|
|
80
|
+
if (mod.addedDeps.length > 0) {
|
|
81
|
+
parts.push(`+deps: ${mod.addedDeps.join(', ')}`);
|
|
82
|
+
}
|
|
83
|
+
if (mod.removedDeps.length > 0) {
|
|
84
|
+
parts.push(`-deps: ${mod.removedDeps.join(', ')}`);
|
|
85
|
+
}
|
|
86
|
+
if (mod.levelChanged) {
|
|
87
|
+
parts.push(`level: ${mod.levelChanged.from} -> ${mod.levelChanged.to}`);
|
|
88
|
+
}
|
|
89
|
+
if (parts.length > 0) {
|
|
90
|
+
summaryParts.push(`${mod.project}: ${parts.join('; ')}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const summary = identical ? 'Graphs are identical' : summaryParts.join('\n');
|
|
94
|
+
return {
|
|
95
|
+
identical,
|
|
96
|
+
diff,
|
|
97
|
+
summary,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=graph-comparator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-comparator.js","sourceRoot":"","sources":["../../../../../../packages/tooling/dev-config/architecture/lib/graph-comparator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Graph Comparator\n *\n * Compares the current generated graph with the saved (blessed) graph.\n * Used in validate mode to ensure developers have updated the graph file.\n */\n\nimport type { EnhancedGraph } from './graph-sorter';\n\n/**\n * Difference between two graphs\n */\nexport interface GraphDiff {\n added: string[];\n removed: string[];\n modified: {\n project: string;\n addedDeps: string[];\n removedDeps: string[];\n levelChanged: { from: number; to: number } | null;\n }[];\n}\n\n/**\n * Comparison result\n */\nexport interface ComparisonResult {\n identical: boolean;\n diff: GraphDiff;\n summary: string;\n}\n\n/**\n * Compare two graphs and return the differences\n *\n * @param current - Currently generated graph\n * @param saved - Previously saved (blessed) graph\n * @returns Comparison result with detailed diff\n */\nexport function compareGraphs(current: EnhancedGraph, saved: EnhancedGraph): ComparisonResult {\n const currentProjects = new Set(Object.keys(current));\n const savedProjects = new Set(Object.keys(saved));\n\n const diff: GraphDiff = {\n added: [],\n removed: [],\n modified: [],\n };\n\n // Find added projects\n for (const project of currentProjects) {\n if (!savedProjects.has(project)) {\n diff.added.push(project);\n }\n }\n\n // Find removed projects\n for (const project of savedProjects) {\n if (!currentProjects.has(project)) {\n diff.removed.push(project);\n }\n }\n\n // Find modified projects\n for (const project of currentProjects) {\n if (!savedProjects.has(project)) continue;\n\n const currentEntry = current[project];\n const savedEntry = saved[project];\n\n const currentDeps = new Set(currentEntry.dependsOn);\n const savedDeps = new Set(savedEntry.dependsOn);\n\n const addedDeps: string[] = [];\n const removedDeps: string[] = [];\n\n for (const dep of currentDeps) {\n if (!savedDeps.has(dep)) {\n addedDeps.push(dep);\n }\n }\n\n for (const dep of savedDeps) {\n if (!currentDeps.has(dep)) {\n removedDeps.push(dep);\n }\n }\n\n const levelChanged =\n currentEntry.level !== savedEntry.level\n ? { from: savedEntry.level, to: currentEntry.level }\n : null;\n\n if (addedDeps.length > 0 || removedDeps.length > 0 || levelChanged) {\n diff.modified.push({\n project,\n addedDeps,\n removedDeps,\n levelChanged,\n });\n }\n }\n\n const identical =\n diff.added.length === 0 && diff.removed.length === 0 && diff.modified.length === 0;\n\n // Generate summary\n const summaryParts: string[] = [];\n\n if (diff.added.length > 0) {\n summaryParts.push(`Added projects: ${diff.added.join(', ')}`);\n }\n\n if (diff.removed.length > 0) {\n summaryParts.push(`Removed projects: ${diff.removed.join(', ')}`);\n }\n\n for (const mod of diff.modified) {\n const parts: string[] = [];\n if (mod.addedDeps.length > 0) {\n parts.push(`+deps: ${mod.addedDeps.join(', ')}`);\n }\n if (mod.removedDeps.length > 0) {\n parts.push(`-deps: ${mod.removedDeps.join(', ')}`);\n }\n if (mod.levelChanged) {\n parts.push(`level: ${mod.levelChanged.from} -> ${mod.levelChanged.to}`);\n }\n if (parts.length > 0) {\n summaryParts.push(`${mod.project}: ${parts.join('; ')}`);\n }\n }\n\n const summary = identical ? 'Graphs are identical' : summaryParts.join('\\n');\n\n return {\n identical,\n diff,\n summary,\n };\n}\n"]}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph Comparator
|
|
3
|
+
*
|
|
4
|
+
* Compares the current generated graph with the saved (blessed) graph.
|
|
5
|
+
* Used in validate mode to ensure developers have updated the graph file.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { EnhancedGraph } from './graph-sorter';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Difference between two graphs
|
|
12
|
+
*/
|
|
13
|
+
export interface GraphDiff {
|
|
14
|
+
added: string[];
|
|
15
|
+
removed: string[];
|
|
16
|
+
modified: {
|
|
17
|
+
project: string;
|
|
18
|
+
addedDeps: string[];
|
|
19
|
+
removedDeps: string[];
|
|
20
|
+
levelChanged: { from: number; to: number } | null;
|
|
21
|
+
}[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Comparison result
|
|
26
|
+
*/
|
|
27
|
+
export interface ComparisonResult {
|
|
28
|
+
identical: boolean;
|
|
29
|
+
diff: GraphDiff;
|
|
30
|
+
summary: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Compare two graphs and return the differences
|
|
35
|
+
*
|
|
36
|
+
* @param current - Currently generated graph
|
|
37
|
+
* @param saved - Previously saved (blessed) graph
|
|
38
|
+
* @returns Comparison result with detailed diff
|
|
39
|
+
*/
|
|
40
|
+
export function compareGraphs(current: EnhancedGraph, saved: EnhancedGraph): ComparisonResult {
|
|
41
|
+
const currentProjects = new Set(Object.keys(current));
|
|
42
|
+
const savedProjects = new Set(Object.keys(saved));
|
|
43
|
+
|
|
44
|
+
const diff: GraphDiff = {
|
|
45
|
+
added: [],
|
|
46
|
+
removed: [],
|
|
47
|
+
modified: [],
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Find added projects
|
|
51
|
+
for (const project of currentProjects) {
|
|
52
|
+
if (!savedProjects.has(project)) {
|
|
53
|
+
diff.added.push(project);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Find removed projects
|
|
58
|
+
for (const project of savedProjects) {
|
|
59
|
+
if (!currentProjects.has(project)) {
|
|
60
|
+
diff.removed.push(project);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Find modified projects
|
|
65
|
+
for (const project of currentProjects) {
|
|
66
|
+
if (!savedProjects.has(project)) continue;
|
|
67
|
+
|
|
68
|
+
const currentEntry = current[project];
|
|
69
|
+
const savedEntry = saved[project];
|
|
70
|
+
|
|
71
|
+
const currentDeps = new Set(currentEntry.dependsOn);
|
|
72
|
+
const savedDeps = new Set(savedEntry.dependsOn);
|
|
73
|
+
|
|
74
|
+
const addedDeps: string[] = [];
|
|
75
|
+
const removedDeps: string[] = [];
|
|
76
|
+
|
|
77
|
+
for (const dep of currentDeps) {
|
|
78
|
+
if (!savedDeps.has(dep)) {
|
|
79
|
+
addedDeps.push(dep);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
for (const dep of savedDeps) {
|
|
84
|
+
if (!currentDeps.has(dep)) {
|
|
85
|
+
removedDeps.push(dep);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const levelChanged =
|
|
90
|
+
currentEntry.level !== savedEntry.level
|
|
91
|
+
? { from: savedEntry.level, to: currentEntry.level }
|
|
92
|
+
: null;
|
|
93
|
+
|
|
94
|
+
if (addedDeps.length > 0 || removedDeps.length > 0 || levelChanged) {
|
|
95
|
+
diff.modified.push({
|
|
96
|
+
project,
|
|
97
|
+
addedDeps,
|
|
98
|
+
removedDeps,
|
|
99
|
+
levelChanged,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const identical =
|
|
105
|
+
diff.added.length === 0 && diff.removed.length === 0 && diff.modified.length === 0;
|
|
106
|
+
|
|
107
|
+
// Generate summary
|
|
108
|
+
const summaryParts: string[] = [];
|
|
109
|
+
|
|
110
|
+
if (diff.added.length > 0) {
|
|
111
|
+
summaryParts.push(`Added projects: ${diff.added.join(', ')}`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (diff.removed.length > 0) {
|
|
115
|
+
summaryParts.push(`Removed projects: ${diff.removed.join(', ')}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
for (const mod of diff.modified) {
|
|
119
|
+
const parts: string[] = [];
|
|
120
|
+
if (mod.addedDeps.length > 0) {
|
|
121
|
+
parts.push(`+deps: ${mod.addedDeps.join(', ')}`);
|
|
122
|
+
}
|
|
123
|
+
if (mod.removedDeps.length > 0) {
|
|
124
|
+
parts.push(`-deps: ${mod.removedDeps.join(', ')}`);
|
|
125
|
+
}
|
|
126
|
+
if (mod.levelChanged) {
|
|
127
|
+
parts.push(`level: ${mod.levelChanged.from} -> ${mod.levelChanged.to}`);
|
|
128
|
+
}
|
|
129
|
+
if (parts.length > 0) {
|
|
130
|
+
summaryParts.push(`${mod.project}: ${parts.join('; ')}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const summary = identical ? 'Graphs are identical' : summaryParts.join('\n');
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
identical,
|
|
138
|
+
diff,
|
|
139
|
+
summary,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates dependency graph from project.json files in the workspace.
|
|
5
|
+
* Reads build.dependsOn and implicitDependencies to determine project relationships.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Generate raw dependency graph from project.json files
|
|
9
|
+
* Returns: { projectName: [dependencyNames] }
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateRawGraph(): Promise<Record<string, string[]>>;
|
|
12
|
+
/**
|
|
13
|
+
* Transform project names to @webpieces/xxx format
|
|
14
|
+
*/
|
|
15
|
+
export declare function transformGraph(rawGraph: Record<string, string[]>): Record<string, string[]>;
|
|
16
|
+
/**
|
|
17
|
+
* Generate complete dependency graph with transformations
|
|
18
|
+
*/
|
|
19
|
+
export declare function generateGraph(): Promise<Record<string, string[]>>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Graph Generator
|
|
4
|
+
*
|
|
5
|
+
* Generates dependency graph from project.json files in the workspace.
|
|
6
|
+
* Reads build.dependsOn and implicitDependencies to determine project relationships.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.generateRawGraph = generateRawGraph;
|
|
10
|
+
exports.transformGraph = transformGraph;
|
|
11
|
+
exports.generateGraph = generateGraph;
|
|
12
|
+
const devkit_1 = require("@nx/devkit");
|
|
13
|
+
/**
|
|
14
|
+
* Projects to exclude from graph validation (tools, configs, etc.)
|
|
15
|
+
*/
|
|
16
|
+
const EXCLUDED_PROJECTS = new Set([]);
|
|
17
|
+
/**
|
|
18
|
+
* Extract project dependencies from project.json's build.dependsOn and implicitDependencies
|
|
19
|
+
*/
|
|
20
|
+
function extractBuildDependencies(projectConfig) {
|
|
21
|
+
const deps = [];
|
|
22
|
+
// 1. Read from build.dependsOn
|
|
23
|
+
const buildTarget = projectConfig.targets?.['build'];
|
|
24
|
+
if (buildTarget && buildTarget.dependsOn) {
|
|
25
|
+
for (const dep of buildTarget.dependsOn) {
|
|
26
|
+
if (typeof dep === 'string') {
|
|
27
|
+
// Format: "project-name:build" or just "build" (for self)
|
|
28
|
+
const match = dep.match(/^([^:]+):build$/);
|
|
29
|
+
if (match) {
|
|
30
|
+
deps.push(match[1]);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// 2. Also read from implicitDependencies
|
|
36
|
+
if (projectConfig.implicitDependencies && Array.isArray(projectConfig.implicitDependencies)) {
|
|
37
|
+
for (const dep of projectConfig.implicitDependencies) {
|
|
38
|
+
if (typeof dep === 'string' && !deps.includes(dep)) {
|
|
39
|
+
deps.push(dep);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return deps.sort();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Generate raw dependency graph from project.json files
|
|
47
|
+
* Returns: { projectName: [dependencyNames] }
|
|
48
|
+
*/
|
|
49
|
+
async function generateRawGraph() {
|
|
50
|
+
const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
|
|
51
|
+
const projectsConfig = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
|
|
52
|
+
const rawDeps = {};
|
|
53
|
+
for (const [projectName, projectConfig] of Object.entries(projectsConfig.projects)) {
|
|
54
|
+
// Skip excluded projects (tools, plugins)
|
|
55
|
+
if (EXCLUDED_PROJECTS.has(projectName)) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// Extract dependencies from build.dependsOn in project.json
|
|
59
|
+
const deps = extractBuildDependencies(projectConfig);
|
|
60
|
+
rawDeps[projectName] = deps;
|
|
61
|
+
}
|
|
62
|
+
return rawDeps;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Transform project names to @webpieces/xxx format
|
|
66
|
+
*/
|
|
67
|
+
function transformGraph(rawGraph) {
|
|
68
|
+
const result = {};
|
|
69
|
+
for (const [projectName, deps] of Object.entries(rawGraph)) {
|
|
70
|
+
// Avoid double prefix if already has @webpieces/
|
|
71
|
+
const transformedName = projectName.startsWith('@webpieces/')
|
|
72
|
+
? projectName
|
|
73
|
+
: `@webpieces/${projectName}`;
|
|
74
|
+
const transformedDeps = deps
|
|
75
|
+
.map((d) => (d.startsWith('@webpieces/') ? d : `@webpieces/${d}`))
|
|
76
|
+
.sort();
|
|
77
|
+
result[transformedName] = transformedDeps;
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Generate complete dependency graph with transformations
|
|
83
|
+
*/
|
|
84
|
+
async function generateGraph() {
|
|
85
|
+
const rawGraph = await generateRawGraph();
|
|
86
|
+
return transformGraph(rawGraph);
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=graph-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-generator.js","sourceRoot":"","sources":["../../../../../../packages/tooling/dev-config/architecture/lib/graph-generator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Graph Generator\n *\n * Generates dependency graph from project.json files in the workspace.\n * Reads build.dependsOn and implicitDependencies to determine project relationships.\n */\n\nimport {\n createProjectGraphAsync,\n readProjectsConfigurationFromProjectGraph,\n ProjectConfiguration,\n} from '@nx/devkit';\n\n/**\n * Projects to exclude from graph validation (tools, configs, etc.)\n */\nconst EXCLUDED_PROJECTS = new Set<string>([]);\n\n/**\n * Extract project dependencies from project.json's build.dependsOn and implicitDependencies\n */\nfunction extractBuildDependencies(projectConfig: ProjectConfiguration): string[] {\n const deps: string[] = [];\n\n // 1. Read from build.dependsOn\n const buildTarget = projectConfig.targets?.['build'];\n if (buildTarget && buildTarget.dependsOn) {\n for (const dep of buildTarget.dependsOn) {\n if (typeof dep === 'string') {\n // Format: \"project-name:build\" or just \"build\" (for self)\n const match = dep.match(/^([^:]+):build$/);\n if (match) {\n deps.push(match[1]);\n }\n }\n }\n }\n\n // 2. Also read from implicitDependencies\n if (projectConfig.implicitDependencies && Array.isArray(projectConfig.implicitDependencies)) {\n for (const dep of projectConfig.implicitDependencies) {\n if (typeof dep === 'string' && !deps.includes(dep)) {\n deps.push(dep);\n }\n }\n }\n\n return deps.sort();\n}\n\n/**\n * Generate raw dependency graph from project.json files\n * Returns: { projectName: [dependencyNames] }\n */\nexport async function generateRawGraph(): Promise<Record<string, string[]>> {\n const projectGraph = await createProjectGraphAsync();\n const projectsConfig = readProjectsConfigurationFromProjectGraph(projectGraph);\n const rawDeps: Record<string, string[]> = {};\n\n for (const [projectName, projectConfig] of Object.entries(projectsConfig.projects)) {\n // Skip excluded projects (tools, plugins)\n if (EXCLUDED_PROJECTS.has(projectName)) {\n continue;\n }\n\n // Extract dependencies from build.dependsOn in project.json\n const deps = extractBuildDependencies(projectConfig);\n rawDeps[projectName] = deps;\n }\n\n return rawDeps;\n}\n\n/**\n * Transform project names to @webpieces/xxx format\n */\nexport function transformGraph(rawGraph: Record<string, string[]>): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n\n for (const [projectName, deps] of Object.entries(rawGraph)) {\n // Avoid double prefix if already has @webpieces/\n const transformedName = projectName.startsWith('@webpieces/')\n ? projectName\n : `@webpieces/${projectName}`;\n\n const transformedDeps = deps\n .map((d) => (d.startsWith('@webpieces/') ? d : `@webpieces/${d}`))\n .sort();\n\n result[transformedName] = transformedDeps;\n }\n\n return result;\n}\n\n/**\n * Generate complete dependency graph with transformations\n */\nexport async function generateGraph(): Promise<Record<string, string[]>> {\n const rawGraph = await generateRawGraph();\n return transformGraph(rawGraph);\n}\n"]}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates dependency graph from project.json files in the workspace.
|
|
5
|
+
* Reads build.dependsOn and implicitDependencies to determine project relationships.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
createProjectGraphAsync,
|
|
10
|
+
readProjectsConfigurationFromProjectGraph,
|
|
11
|
+
ProjectConfiguration,
|
|
12
|
+
} from '@nx/devkit';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Projects to exclude from graph validation (tools, configs, etc.)
|
|
16
|
+
*/
|
|
17
|
+
const EXCLUDED_PROJECTS = new Set<string>([]);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Extract project dependencies from project.json's build.dependsOn and implicitDependencies
|
|
21
|
+
*/
|
|
22
|
+
function extractBuildDependencies(projectConfig: ProjectConfiguration): string[] {
|
|
23
|
+
const deps: string[] = [];
|
|
24
|
+
|
|
25
|
+
// 1. Read from build.dependsOn
|
|
26
|
+
const buildTarget = projectConfig.targets?.['build'];
|
|
27
|
+
if (buildTarget && buildTarget.dependsOn) {
|
|
28
|
+
for (const dep of buildTarget.dependsOn) {
|
|
29
|
+
if (typeof dep === 'string') {
|
|
30
|
+
// Format: "project-name:build" or just "build" (for self)
|
|
31
|
+
const match = dep.match(/^([^:]+):build$/);
|
|
32
|
+
if (match) {
|
|
33
|
+
deps.push(match[1]);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 2. Also read from implicitDependencies
|
|
40
|
+
if (projectConfig.implicitDependencies && Array.isArray(projectConfig.implicitDependencies)) {
|
|
41
|
+
for (const dep of projectConfig.implicitDependencies) {
|
|
42
|
+
if (typeof dep === 'string' && !deps.includes(dep)) {
|
|
43
|
+
deps.push(dep);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return deps.sort();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Generate raw dependency graph from project.json files
|
|
53
|
+
* Returns: { projectName: [dependencyNames] }
|
|
54
|
+
*/
|
|
55
|
+
export async function generateRawGraph(): Promise<Record<string, string[]>> {
|
|
56
|
+
const projectGraph = await createProjectGraphAsync();
|
|
57
|
+
const projectsConfig = readProjectsConfigurationFromProjectGraph(projectGraph);
|
|
58
|
+
const rawDeps: Record<string, string[]> = {};
|
|
59
|
+
|
|
60
|
+
for (const [projectName, projectConfig] of Object.entries(projectsConfig.projects)) {
|
|
61
|
+
// Skip excluded projects (tools, plugins)
|
|
62
|
+
if (EXCLUDED_PROJECTS.has(projectName)) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Extract dependencies from build.dependsOn in project.json
|
|
67
|
+
const deps = extractBuildDependencies(projectConfig);
|
|
68
|
+
rawDeps[projectName] = deps;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return rawDeps;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Transform project names to @webpieces/xxx format
|
|
76
|
+
*/
|
|
77
|
+
export function transformGraph(rawGraph: Record<string, string[]>): Record<string, string[]> {
|
|
78
|
+
const result: Record<string, string[]> = {};
|
|
79
|
+
|
|
80
|
+
for (const [projectName, deps] of Object.entries(rawGraph)) {
|
|
81
|
+
// Avoid double prefix if already has @webpieces/
|
|
82
|
+
const transformedName = projectName.startsWith('@webpieces/')
|
|
83
|
+
? projectName
|
|
84
|
+
: `@webpieces/${projectName}`;
|
|
85
|
+
|
|
86
|
+
const transformedDeps = deps
|
|
87
|
+
.map((d) => (d.startsWith('@webpieces/') ? d : `@webpieces/${d}`))
|
|
88
|
+
.sort();
|
|
89
|
+
|
|
90
|
+
result[transformedName] = transformedDeps;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Generate complete dependency graph with transformations
|
|
98
|
+
*/
|
|
99
|
+
export async function generateGraph(): Promise<Record<string, string[]>> {
|
|
100
|
+
const rawGraph = await generateRawGraph();
|
|
101
|
+
return transformGraph(rawGraph);
|
|
102
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph Loader
|
|
3
|
+
*
|
|
4
|
+
* Handles loading and saving the blessed dependency graph file.
|
|
5
|
+
* The graph is stored at architecture/dependencies.json in the workspace root.
|
|
6
|
+
*/
|
|
7
|
+
import type { EnhancedGraph } from './graph-sorter';
|
|
8
|
+
/**
|
|
9
|
+
* Default path for the dependencies file (relative to workspace root)
|
|
10
|
+
*/
|
|
11
|
+
export declare const DEFAULT_GRAPH_PATH = "architecture/dependencies.json";
|
|
12
|
+
/**
|
|
13
|
+
* Load the blessed graph from disk
|
|
14
|
+
*
|
|
15
|
+
* @param workspaceRoot - Absolute path to workspace root
|
|
16
|
+
* @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)
|
|
17
|
+
* @returns The blessed graph, or null if file doesn't exist
|
|
18
|
+
*/
|
|
19
|
+
export declare function loadBlessedGraph(workspaceRoot: string, graphPath?: string): EnhancedGraph | null;
|
|
20
|
+
/**
|
|
21
|
+
* Save the graph to disk
|
|
22
|
+
*
|
|
23
|
+
* @param graph - The graph to save
|
|
24
|
+
* @param workspaceRoot - Absolute path to workspace root
|
|
25
|
+
* @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)
|
|
26
|
+
*/
|
|
27
|
+
export declare function saveGraph(graph: EnhancedGraph, workspaceRoot: string, graphPath?: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Check if the graph file exists
|
|
30
|
+
*/
|
|
31
|
+
export declare function graphFileExists(workspaceRoot: string, graphPath?: string): boolean;
|