@webpieces/dev-config 0.0.0-dev ā 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__/catch-error-pattern.test.ts +0 -1
- package/eslint-plugin/__tests__/max-file-lines.test.ts +29 -17
- package/eslint-plugin/__tests__/max-method-lines.test.ts +27 -15
- package/eslint-plugin/__tests__/no-unmanaged-exceptions.test.ts +359 -0
- package/eslint-plugin/index.d.ts +9 -0
- package/eslint-plugin/index.js +11 -0
- package/eslint-plugin/index.js.map +1 -1
- package/eslint-plugin/index.ts +11 -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.js +11 -11
- package/eslint-plugin/rules/max-file-lines.js.map +1 -1
- package/eslint-plugin/rules/max-file-lines.ts +11 -11
- package/eslint-plugin/rules/max-method-lines.js +71 -88
- package/eslint-plugin/rules/max-method-lines.js.map +1 -1
- package/eslint-plugin/rules/max-method-lines.ts +85 -102
- 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 -7
- 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,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate Executor
|
|
3
|
+
*
|
|
4
|
+
* Generates the architecture dependency graph and saves it to architecture/dependencies.json.
|
|
5
|
+
* Also validates that package.json dependencies match project.json.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* nx run architecture:generate
|
|
9
|
+
*/
|
|
10
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
11
|
+
export interface GenerateExecutorOptions {
|
|
12
|
+
graphPath?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ExecutorResult {
|
|
15
|
+
success: boolean;
|
|
16
|
+
}
|
|
17
|
+
export default function runExecutor(options: GenerateExecutorOptions, context: ExecutorContext): Promise<ExecutorResult>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Generate Executor
|
|
4
|
+
*
|
|
5
|
+
* Generates the architecture dependency graph and saves it to architecture/dependencies.json.
|
|
6
|
+
* Also validates that package.json dependencies match project.json.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* nx run architecture:generate
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.default = runExecutor;
|
|
13
|
+
const graph_generator_1 = require("../../lib/graph-generator");
|
|
14
|
+
const graph_sorter_1 = require("../../lib/graph-sorter");
|
|
15
|
+
const package_validator_1 = require("../../lib/package-validator");
|
|
16
|
+
const graph_loader_1 = require("../../lib/graph-loader");
|
|
17
|
+
async function runExecutor(options, context) {
|
|
18
|
+
const { graphPath } = options;
|
|
19
|
+
const workspaceRoot = context.root;
|
|
20
|
+
console.log('\nš Architecture Graph Generator\n');
|
|
21
|
+
try {
|
|
22
|
+
// Step 1: Generate current graph from project.json files
|
|
23
|
+
console.log('š Generating dependency graph from project.json files...');
|
|
24
|
+
const rawGraph = await (0, graph_generator_1.generateGraph)();
|
|
25
|
+
// Step 2: Topological sort (validates acyclic and assigns levels)
|
|
26
|
+
console.log('š Computing topological layers...');
|
|
27
|
+
let enhancedGraph;
|
|
28
|
+
try {
|
|
29
|
+
enhancedGraph = (0, graph_sorter_1.sortGraphTopologically)(rawGraph);
|
|
30
|
+
console.log('ā
Graph is acyclic');
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
34
|
+
console.error('ā Circular dependency detected!');
|
|
35
|
+
console.error(error.message);
|
|
36
|
+
return { success: false };
|
|
37
|
+
}
|
|
38
|
+
// Step 3: Validate package.json dependencies match
|
|
39
|
+
console.log('š¦ Validating package.json dependencies match project.json...');
|
|
40
|
+
const packageValidation = await (0, package_validator_1.validatePackageJsonDependencies)(enhancedGraph, workspaceRoot);
|
|
41
|
+
if (!packageValidation.valid) {
|
|
42
|
+
console.error('ā Package.json validation failed!');
|
|
43
|
+
for (const error of packageValidation.errors) {
|
|
44
|
+
console.error(` ${error}`);
|
|
45
|
+
}
|
|
46
|
+
return { success: false };
|
|
47
|
+
}
|
|
48
|
+
console.log('ā
Package.json dependencies match');
|
|
49
|
+
// Step 4: Save the graph
|
|
50
|
+
console.log('š¾ Saving graph to architecture/dependencies.json...');
|
|
51
|
+
(0, graph_loader_1.saveGraph)(enhancedGraph, workspaceRoot, graphPath);
|
|
52
|
+
console.log('ā
Graph saved successfully');
|
|
53
|
+
// Print summary
|
|
54
|
+
const projectCount = Object.keys(enhancedGraph).length;
|
|
55
|
+
const levels = new Set(Object.values(enhancedGraph).map((e) => e.level));
|
|
56
|
+
console.log(`\nš Graph Summary:`);
|
|
57
|
+
console.log(` Projects: ${projectCount}`);
|
|
58
|
+
console.log(` Levels: ${levels.size} (0-${Math.max(...levels)})`);
|
|
59
|
+
return { success: true };
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
63
|
+
console.error('ā Graph generation failed:', error.message);
|
|
64
|
+
return { success: false };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/dev-config/architecture/executors/generate/executor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Generate Executor\n *\n * Generates the architecture dependency graph and saves it to architecture/dependencies.json.\n * Also validates that package.json dependencies match project.json.\n *\n * Usage:\n * nx run architecture:generate\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport { generateGraph } from '../../lib/graph-generator';\nimport { sortGraphTopologically } from '../../lib/graph-sorter';\nimport { validatePackageJsonDependencies } from '../../lib/package-validator';\nimport { saveGraph } from '../../lib/graph-loader';\n\nexport interface GenerateExecutorOptions {\n graphPath?: string;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nexport default async function runExecutor(\n options: GenerateExecutorOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const { graphPath } = options;\n const workspaceRoot = context.root;\n\n console.log('\\nš Architecture Graph Generator\\n');\n\n try {\n // Step 1: Generate current graph from project.json files\n console.log('š Generating dependency graph from project.json files...');\n const rawGraph = await generateGraph();\n\n // Step 2: Topological sort (validates acyclic and assigns levels)\n console.log('š Computing topological layers...');\n let enhancedGraph;\n try {\n enhancedGraph = sortGraphTopologically(rawGraph);\n console.log('ā
Graph is acyclic');\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n console.error('ā Circular dependency detected!');\n console.error(error.message);\n return { success: false };\n }\n\n // Step 3: Validate package.json dependencies match\n console.log('š¦ Validating package.json dependencies match project.json...');\n const packageValidation = await validatePackageJsonDependencies(enhancedGraph, workspaceRoot);\n\n if (!packageValidation.valid) {\n console.error('ā Package.json validation failed!');\n for (const error of packageValidation.errors) {\n console.error(` ${error}`);\n }\n return { success: false };\n }\n console.log('ā
Package.json dependencies match');\n\n // Step 4: Save the graph\n console.log('š¾ Saving graph to architecture/dependencies.json...');\n saveGraph(enhancedGraph, workspaceRoot, graphPath);\n console.log('ā
Graph saved successfully');\n\n // Print summary\n const projectCount = Object.keys(enhancedGraph).length;\n const levels = new Set(Object.values(enhancedGraph).map((e) => e.level));\n console.log(`\\nš Graph Summary:`);\n console.log(` Projects: ${projectCount}`);\n console.log(` Levels: ${levels.size} (0-${Math.max(...levels)})`);\n\n return { success: true };\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n console.error('ā Graph generation failed:', error.message);\n return { success: false };\n }\n}\n"]}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate Executor
|
|
3
|
+
*
|
|
4
|
+
* Generates the architecture dependency graph and saves it to architecture/dependencies.json.
|
|
5
|
+
* Also validates that package.json dependencies match project.json.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* nx run architecture:generate
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
12
|
+
import { generateGraph } from '../../lib/graph-generator';
|
|
13
|
+
import { sortGraphTopologically } from '../../lib/graph-sorter';
|
|
14
|
+
import { validatePackageJsonDependencies } from '../../lib/package-validator';
|
|
15
|
+
import { saveGraph } from '../../lib/graph-loader';
|
|
16
|
+
|
|
17
|
+
export interface GenerateExecutorOptions {
|
|
18
|
+
graphPath?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ExecutorResult {
|
|
22
|
+
success: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default async function runExecutor(
|
|
26
|
+
options: GenerateExecutorOptions,
|
|
27
|
+
context: ExecutorContext
|
|
28
|
+
): Promise<ExecutorResult> {
|
|
29
|
+
const { graphPath } = options;
|
|
30
|
+
const workspaceRoot = context.root;
|
|
31
|
+
|
|
32
|
+
console.log('\nš Architecture Graph Generator\n');
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
// Step 1: Generate current graph from project.json files
|
|
36
|
+
console.log('š Generating dependency graph from project.json files...');
|
|
37
|
+
const rawGraph = await generateGraph();
|
|
38
|
+
|
|
39
|
+
// Step 2: Topological sort (validates acyclic and assigns levels)
|
|
40
|
+
console.log('š Computing topological layers...');
|
|
41
|
+
let enhancedGraph;
|
|
42
|
+
try {
|
|
43
|
+
enhancedGraph = sortGraphTopologically(rawGraph);
|
|
44
|
+
console.log('ā
Graph is acyclic');
|
|
45
|
+
} catch (err: unknown) {
|
|
46
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
47
|
+
console.error('ā Circular dependency detected!');
|
|
48
|
+
console.error(error.message);
|
|
49
|
+
return { success: false };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Step 3: Validate package.json dependencies match
|
|
53
|
+
console.log('š¦ Validating package.json dependencies match project.json...');
|
|
54
|
+
const packageValidation = await validatePackageJsonDependencies(enhancedGraph, workspaceRoot);
|
|
55
|
+
|
|
56
|
+
if (!packageValidation.valid) {
|
|
57
|
+
console.error('ā Package.json validation failed!');
|
|
58
|
+
for (const error of packageValidation.errors) {
|
|
59
|
+
console.error(` ${error}`);
|
|
60
|
+
}
|
|
61
|
+
return { success: false };
|
|
62
|
+
}
|
|
63
|
+
console.log('ā
Package.json dependencies match');
|
|
64
|
+
|
|
65
|
+
// Step 4: Save the graph
|
|
66
|
+
console.log('š¾ Saving graph to architecture/dependencies.json...');
|
|
67
|
+
saveGraph(enhancedGraph, workspaceRoot, graphPath);
|
|
68
|
+
console.log('ā
Graph saved successfully');
|
|
69
|
+
|
|
70
|
+
// Print summary
|
|
71
|
+
const projectCount = Object.keys(enhancedGraph).length;
|
|
72
|
+
const levels = new Set(Object.values(enhancedGraph).map((e) => e.level));
|
|
73
|
+
console.log(`\nš Graph Summary:`);
|
|
74
|
+
console.log(` Projects: ${projectCount}`);
|
|
75
|
+
console.log(` Levels: ${levels.size} (0-${Math.max(...levels)})`);
|
|
76
|
+
|
|
77
|
+
return { success: true };
|
|
78
|
+
} catch (err: unknown) {
|
|
79
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
80
|
+
console.error('ā Graph generation failed:', error.message);
|
|
81
|
+
return { success: false };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"title": "Generate Executor",
|
|
4
|
+
"description": "Generates the architecture dependency graph and saves it",
|
|
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,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate Architecture Unchanged Executor
|
|
3
|
+
*
|
|
4
|
+
* Validates that the current architecture graph matches the saved blessed graph.
|
|
5
|
+
* This ensures no unapproved architecture changes have been made.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* nx run architecture:validate-architecture-unchanged
|
|
9
|
+
*/
|
|
10
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
11
|
+
export interface ValidateArchitectureUnchangedOptions {
|
|
12
|
+
graphPath?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ExecutorResult {
|
|
15
|
+
success: boolean;
|
|
16
|
+
}
|
|
17
|
+
export default function runExecutor(options: ValidateArchitectureUnchangedOptions, context: ExecutorContext): Promise<ExecutorResult>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Validate Architecture Unchanged Executor
|
|
4
|
+
*
|
|
5
|
+
* Validates that the current architecture graph matches the saved blessed graph.
|
|
6
|
+
* This ensures no unapproved architecture changes have been made.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* nx run architecture:validate-architecture-unchanged
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.default = runExecutor;
|
|
13
|
+
const graph_generator_1 = require("../../lib/graph-generator");
|
|
14
|
+
const graph_sorter_1 = require("../../lib/graph-sorter");
|
|
15
|
+
const graph_comparator_1 = require("../../lib/graph-comparator");
|
|
16
|
+
const graph_loader_1 = require("../../lib/graph-loader");
|
|
17
|
+
async function runExecutor(options, context) {
|
|
18
|
+
const { graphPath } = options;
|
|
19
|
+
const workspaceRoot = context.root;
|
|
20
|
+
console.log('\nš Validating Architecture Unchanged\n');
|
|
21
|
+
try {
|
|
22
|
+
// Check if saved graph exists
|
|
23
|
+
if (!(0, graph_loader_1.graphFileExists)(workspaceRoot, graphPath)) {
|
|
24
|
+
console.error('ā No saved graph found at architecture/dependencies.json');
|
|
25
|
+
console.error(' Run: nx run architecture:generate first');
|
|
26
|
+
return { success: false };
|
|
27
|
+
}
|
|
28
|
+
// Step 1: Generate current graph from project.json files
|
|
29
|
+
console.log('š Generating current dependency graph...');
|
|
30
|
+
const rawGraph = await (0, graph_generator_1.generateGraph)();
|
|
31
|
+
// Step 2: Topological sort (to get enhanced graph with levels)
|
|
32
|
+
console.log('š Computing topological layers...');
|
|
33
|
+
const currentGraph = (0, graph_sorter_1.sortGraphTopologically)(rawGraph);
|
|
34
|
+
// Step 3: Load saved graph
|
|
35
|
+
console.log('š Loading saved graph...');
|
|
36
|
+
const savedGraph = (0, graph_loader_1.loadBlessedGraph)(workspaceRoot, graphPath);
|
|
37
|
+
if (!savedGraph) {
|
|
38
|
+
console.error('ā Could not load saved graph');
|
|
39
|
+
return { success: false };
|
|
40
|
+
}
|
|
41
|
+
// Step 4: Compare graphs
|
|
42
|
+
console.log('š Comparing current graph to saved graph...');
|
|
43
|
+
const comparison = (0, graph_comparator_1.compareGraphs)(currentGraph, savedGraph);
|
|
44
|
+
if (comparison.identical) {
|
|
45
|
+
console.log('ā
Architecture unchanged - current graph matches saved graph');
|
|
46
|
+
return { success: true };
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
console.error('ā Architecture has changed since last update!');
|
|
50
|
+
console.error('\nDifferences:');
|
|
51
|
+
console.error(comparison.summary);
|
|
52
|
+
console.error('\nTo fix:');
|
|
53
|
+
console.error(' 1. Review the changes above');
|
|
54
|
+
console.error(' 2. If intentional, run: nx run architecture:generate');
|
|
55
|
+
console.error(' 3. Commit the updated architecture/dependencies.json');
|
|
56
|
+
return { success: false };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
61
|
+
console.error('ā Architecture validation failed:', error.message);
|
|
62
|
+
return { success: false };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/dev-config/architecture/executors/validate-architecture-unchanged/executor.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;AAgBH,8BAwDC;AArED,+DAA0D;AAC1D,yDAAgE;AAChE,iEAA2D;AAC3D,yDAA2E;AAU5D,KAAK,UAAU,WAAW,CACrC,OAA6C,EAC7C,OAAwB;IAExB,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC9B,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAEnC,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;IAExD,IAAI,CAAC;QACD,8BAA8B;QAC9B,IAAI,CAAC,IAAA,8BAAe,EAAC,aAAa,EAAE,SAAS,CAAC,EAAE,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAC1E,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAC5D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC9B,CAAC;QAED,yDAAyD;QACzD,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,MAAM,IAAA,+BAAa,GAAE,CAAC;QAEvC,+DAA+D;QAC/D,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAClD,MAAM,YAAY,GAAG,IAAA,qCAAsB,EAAC,QAAQ,CAAC,CAAC;QAEtD,2BAA2B;QAC3B,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,MAAM,UAAU,GAAG,IAAA,+BAAgB,EAAC,aAAa,EAAE,SAAS,CAAC,CAAC;QAE9D,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAC9C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC9B,CAAC;QAED,yBAAyB;QACzB,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,IAAA,gCAAa,EAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAE3D,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;YAC5E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC7B,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;YAC/D,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAChC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAClC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;YAC/C,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;YACxE,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;YACxE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC9B,CAAC;IACL,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAClE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;AACL,CAAC","sourcesContent":["/**\n * Validate Architecture Unchanged Executor\n *\n * Validates that the current architecture graph matches the saved blessed graph.\n * This ensures no unapproved architecture changes have been made.\n *\n * Usage:\n * nx run architecture:validate-architecture-unchanged\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport { generateGraph } from '../../lib/graph-generator';\nimport { sortGraphTopologically } from '../../lib/graph-sorter';\nimport { compareGraphs } from '../../lib/graph-comparator';\nimport { loadBlessedGraph, graphFileExists } from '../../lib/graph-loader';\n\nexport interface ValidateArchitectureUnchangedOptions {\n graphPath?: string;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nexport default async function runExecutor(\n options: ValidateArchitectureUnchangedOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const { graphPath } = options;\n const workspaceRoot = context.root;\n\n console.log('\\nš Validating Architecture Unchanged\\n');\n\n try {\n // Check if saved graph exists\n if (!graphFileExists(workspaceRoot, graphPath)) {\n console.error('ā No saved graph found at architecture/dependencies.json');\n console.error(' Run: nx run architecture:generate first');\n return { success: false };\n }\n\n // Step 1: Generate current graph from project.json files\n console.log('š Generating current dependency graph...');\n const rawGraph = await generateGraph();\n\n // Step 2: Topological sort (to get enhanced graph with levels)\n console.log('š Computing topological layers...');\n const currentGraph = sortGraphTopologically(rawGraph);\n\n // Step 3: Load saved graph\n console.log('š Loading saved graph...');\n const savedGraph = loadBlessedGraph(workspaceRoot, graphPath);\n\n if (!savedGraph) {\n console.error('ā Could not load saved graph');\n return { success: false };\n }\n\n // Step 4: Compare graphs\n console.log('š Comparing current graph to saved graph...');\n const comparison = compareGraphs(currentGraph, savedGraph);\n\n if (comparison.identical) {\n console.log('ā
Architecture unchanged - current graph matches saved graph');\n return { success: true };\n } else {\n console.error('ā Architecture has changed since last update!');\n console.error('\\nDifferences:');\n console.error(comparison.summary);\n console.error('\\nTo fix:');\n console.error(' 1. Review the changes above');\n console.error(' 2. If intentional, run: nx run architecture:generate');\n console.error(' 3. Commit the updated architecture/dependencies.json');\n return { success: false };\n }\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n console.error('ā Architecture validation failed:', error.message);\n return { success: false };\n }\n}\n"]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate Architecture Unchanged Executor
|
|
3
|
+
*
|
|
4
|
+
* Validates that the current architecture graph matches the saved blessed graph.
|
|
5
|
+
* This ensures no unapproved architecture changes have been made.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* nx run architecture:validate-architecture-unchanged
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
12
|
+
import { generateGraph } from '../../lib/graph-generator';
|
|
13
|
+
import { sortGraphTopologically } from '../../lib/graph-sorter';
|
|
14
|
+
import { compareGraphs } from '../../lib/graph-comparator';
|
|
15
|
+
import { loadBlessedGraph, graphFileExists } from '../../lib/graph-loader';
|
|
16
|
+
|
|
17
|
+
export interface ValidateArchitectureUnchangedOptions {
|
|
18
|
+
graphPath?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ExecutorResult {
|
|
22
|
+
success: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default async function runExecutor(
|
|
26
|
+
options: ValidateArchitectureUnchangedOptions,
|
|
27
|
+
context: ExecutorContext
|
|
28
|
+
): Promise<ExecutorResult> {
|
|
29
|
+
const { graphPath } = options;
|
|
30
|
+
const workspaceRoot = context.root;
|
|
31
|
+
|
|
32
|
+
console.log('\nš Validating Architecture Unchanged\n');
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
// Check if saved graph exists
|
|
36
|
+
if (!graphFileExists(workspaceRoot, graphPath)) {
|
|
37
|
+
console.error('ā No saved graph found at architecture/dependencies.json');
|
|
38
|
+
console.error(' Run: nx run architecture:generate first');
|
|
39
|
+
return { success: false };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Step 1: Generate current graph from project.json files
|
|
43
|
+
console.log('š Generating current dependency graph...');
|
|
44
|
+
const rawGraph = await generateGraph();
|
|
45
|
+
|
|
46
|
+
// Step 2: Topological sort (to get enhanced graph with levels)
|
|
47
|
+
console.log('š Computing topological layers...');
|
|
48
|
+
const currentGraph = sortGraphTopologically(rawGraph);
|
|
49
|
+
|
|
50
|
+
// Step 3: Load saved graph
|
|
51
|
+
console.log('š Loading saved graph...');
|
|
52
|
+
const savedGraph = loadBlessedGraph(workspaceRoot, graphPath);
|
|
53
|
+
|
|
54
|
+
if (!savedGraph) {
|
|
55
|
+
console.error('ā Could not load saved graph');
|
|
56
|
+
return { success: false };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Step 4: Compare graphs
|
|
60
|
+
console.log('š Comparing current graph to saved graph...');
|
|
61
|
+
const comparison = compareGraphs(currentGraph, savedGraph);
|
|
62
|
+
|
|
63
|
+
if (comparison.identical) {
|
|
64
|
+
console.log('ā
Architecture unchanged - current graph matches saved graph');
|
|
65
|
+
return { success: true };
|
|
66
|
+
} else {
|
|
67
|
+
console.error('ā Architecture has changed since last update!');
|
|
68
|
+
console.error('\nDifferences:');
|
|
69
|
+
console.error(comparison.summary);
|
|
70
|
+
console.error('\nTo fix:');
|
|
71
|
+
console.error(' 1. Review the changes above');
|
|
72
|
+
console.error(' 2. If intentional, run: nx run architecture:generate');
|
|
73
|
+
console.error(' 3. Commit the updated architecture/dependencies.json');
|
|
74
|
+
return { success: false };
|
|
75
|
+
}
|
|
76
|
+
} catch (err: unknown) {
|
|
77
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
78
|
+
console.error('ā Architecture validation failed:', error.message);
|
|
79
|
+
return { success: false };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"title": "Validate Architecture Unchanged Executor",
|
|
4
|
+
"description": "Validates that the current architecture matches the saved 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,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate No Cycles Executor
|
|
3
|
+
*
|
|
4
|
+
* Validates that the architecture dependency graph has no circular dependencies.
|
|
5
|
+
* This is a fast check that only validates acyclicity.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* nx run architecture:validate-no-cycles
|
|
9
|
+
*/
|
|
10
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
11
|
+
export interface ValidateNoCyclesOptions {
|
|
12
|
+
}
|
|
13
|
+
export interface ExecutorResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
}
|
|
16
|
+
export default function runExecutor(_options: ValidateNoCyclesOptions, _context: ExecutorContext): Promise<ExecutorResult>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Validate No Cycles Executor
|
|
4
|
+
*
|
|
5
|
+
* Validates that the architecture dependency graph has no circular dependencies.
|
|
6
|
+
* This is a fast check that only validates acyclicity.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* nx run architecture:validate-no-cycles
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.default = runExecutor;
|
|
13
|
+
const graph_generator_1 = require("../../lib/graph-generator");
|
|
14
|
+
const graph_sorter_1 = require("../../lib/graph-sorter");
|
|
15
|
+
async function runExecutor(_options, _context) {
|
|
16
|
+
console.log('\nš Validating No Circular Dependencies\n');
|
|
17
|
+
try {
|
|
18
|
+
// Step 1: Generate current graph from project.json files
|
|
19
|
+
console.log('š Generating dependency graph from project.json files...');
|
|
20
|
+
const rawGraph = await (0, graph_generator_1.generateGraph)();
|
|
21
|
+
// Step 2: Topological sort (validates acyclic)
|
|
22
|
+
console.log('š Checking for cycles (topological sort)...');
|
|
23
|
+
try {
|
|
24
|
+
(0, graph_sorter_1.sortGraphTopologically)(rawGraph);
|
|
25
|
+
console.log('ā
No circular dependencies detected!');
|
|
26
|
+
// Print summary
|
|
27
|
+
const projectCount = Object.keys(rawGraph).length;
|
|
28
|
+
console.log(`\nš Summary: ${projectCount} projects, all acyclic`);
|
|
29
|
+
return { success: true };
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
33
|
+
console.error('ā Circular dependency detected!');
|
|
34
|
+
console.error(error.message);
|
|
35
|
+
console.error('\nTo fix:');
|
|
36
|
+
console.error(' 1. Review the cycle above');
|
|
37
|
+
console.error(' 2. Break the cycle by refactoring dependencies');
|
|
38
|
+
console.error(' 3. Run this check again');
|
|
39
|
+
return { success: false };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
44
|
+
console.error('ā Cycle validation failed:', error.message);
|
|
45
|
+
return { success: false };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/dev-config/architecture/executors/validate-no-cycles/executor.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;AAcH,8BAqCC;AAhDD,+DAA0D;AAC1D,yDAAgE;AAUjD,KAAK,UAAU,WAAW,CACrC,QAAiC,EACjC,QAAyB;IAEzB,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAE1D,IAAI,CAAC;QACD,yDAAyD;QACzD,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;QACzE,MAAM,QAAQ,GAAG,MAAM,IAAA,+BAAa,GAAE,CAAC;QAEvC,+CAA+C;QAC/C,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC5D,IAAI,CAAC;YACD,IAAA,qCAAsB,EAAC,QAAQ,CAAC,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;YAEpD,gBAAgB;YAChB,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,iBAAiB,YAAY,wBAAwB,CAAC,CAAC;YAEnE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAClE,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACjD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7B,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;YAClE,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC3C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC9B,CAAC;IACL,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;AACL,CAAC","sourcesContent":["/**\n * Validate No Cycles Executor\n *\n * Validates that the architecture dependency graph has no circular dependencies.\n * This is a fast check that only validates acyclicity.\n *\n * Usage:\n * nx run architecture:validate-no-cycles\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport { generateGraph } from '../../lib/graph-generator';\nimport { sortGraphTopologically } from '../../lib/graph-sorter';\n\nexport interface ValidateNoCyclesOptions {\n // No options needed\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nexport default async function runExecutor(\n _options: ValidateNoCyclesOptions,\n _context: ExecutorContext\n): Promise<ExecutorResult> {\n console.log('\\nš Validating No Circular Dependencies\\n');\n\n try {\n // Step 1: Generate current graph from project.json files\n console.log('š Generating dependency graph from project.json files...');\n const rawGraph = await generateGraph();\n\n // Step 2: Topological sort (validates acyclic)\n console.log('š Checking for cycles (topological sort)...');\n try {\n sortGraphTopologically(rawGraph);\n console.log('ā
No circular dependencies detected!');\n\n // Print summary\n const projectCount = Object.keys(rawGraph).length;\n console.log(`\\nš Summary: ${projectCount} projects, all acyclic`);\n\n return { success: true };\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n console.error('ā Circular dependency detected!');\n console.error(error.message);\n console.error('\\nTo fix:');\n console.error(' 1. Review the cycle above');\n console.error(' 2. Break the cycle by refactoring dependencies');\n console.error(' 3. Run this check again');\n return { success: false };\n }\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n console.error('ā Cycle validation failed:', error.message);\n return { success: false };\n }\n}\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate No Cycles Executor
|
|
3
|
+
*
|
|
4
|
+
* Validates that the architecture dependency graph has no circular dependencies.
|
|
5
|
+
* This is a fast check that only validates acyclicity.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* nx run architecture:validate-no-cycles
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
12
|
+
import { generateGraph } from '../../lib/graph-generator';
|
|
13
|
+
import { sortGraphTopologically } from '../../lib/graph-sorter';
|
|
14
|
+
|
|
15
|
+
export interface ValidateNoCyclesOptions {
|
|
16
|
+
// No options needed
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ExecutorResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default async function runExecutor(
|
|
24
|
+
_options: ValidateNoCyclesOptions,
|
|
25
|
+
_context: ExecutorContext
|
|
26
|
+
): Promise<ExecutorResult> {
|
|
27
|
+
console.log('\nš Validating No Circular Dependencies\n');
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
// Step 1: Generate current graph from project.json files
|
|
31
|
+
console.log('š Generating dependency graph from project.json files...');
|
|
32
|
+
const rawGraph = await generateGraph();
|
|
33
|
+
|
|
34
|
+
// Step 2: Topological sort (validates acyclic)
|
|
35
|
+
console.log('š Checking for cycles (topological sort)...');
|
|
36
|
+
try {
|
|
37
|
+
sortGraphTopologically(rawGraph);
|
|
38
|
+
console.log('ā
No circular dependencies detected!');
|
|
39
|
+
|
|
40
|
+
// Print summary
|
|
41
|
+
const projectCount = Object.keys(rawGraph).length;
|
|
42
|
+
console.log(`\nš Summary: ${projectCount} projects, all acyclic`);
|
|
43
|
+
|
|
44
|
+
return { success: true };
|
|
45
|
+
} catch (err: unknown) {
|
|
46
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
47
|
+
console.error('ā Circular dependency detected!');
|
|
48
|
+
console.error(error.message);
|
|
49
|
+
console.error('\nTo fix:');
|
|
50
|
+
console.error(' 1. Review the cycle above');
|
|
51
|
+
console.error(' 2. Break the cycle by refactoring dependencies');
|
|
52
|
+
console.error(' 3. Run this check again');
|
|
53
|
+
return { success: false };
|
|
54
|
+
}
|
|
55
|
+
} catch (err: unknown) {
|
|
56
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
57
|
+
console.error('ā Cycle validation failed:', error.message);
|
|
58
|
+
return { success: false };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate No Skip-Level Dependencies Executor
|
|
3
|
+
*
|
|
4
|
+
* Validates that no project has redundant transitive dependencies.
|
|
5
|
+
* If project A depends on B, and B transitively brings in C, then A should NOT
|
|
6
|
+
* also directly depend on C (it's redundant and clutters the dependency graph).
|
|
7
|
+
*
|
|
8
|
+
* This keeps the architecture graph clean for visualization and human understanding.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* nx run architecture:validate-no-skiplevel-deps
|
|
12
|
+
*/
|
|
13
|
+
import type { ExecutorContext } from '@nx/devkit';
|
|
14
|
+
export interface ValidateNoSkipLevelDepsOptions {
|
|
15
|
+
}
|
|
16
|
+
export interface ExecutorResult {
|
|
17
|
+
success: boolean;
|
|
18
|
+
}
|
|
19
|
+
export default function runExecutor(_options: ValidateNoSkipLevelDepsOptions, context: ExecutorContext): Promise<ExecutorResult>;
|