@webpieces/dev-config 0.2.17 → 0.2.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +44 -1
  2. package/architecture/executors/generate/executor.d.ts +17 -0
  3. package/architecture/executors/generate/executor.js +67 -0
  4. package/architecture/executors/generate/executor.js.map +1 -0
  5. package/architecture/executors/generate/executor.ts +83 -0
  6. package/architecture/executors/generate/schema.json +14 -0
  7. package/architecture/executors/validate-architecture-unchanged/executor.d.ts +17 -0
  8. package/architecture/executors/validate-architecture-unchanged/executor.js +65 -0
  9. package/architecture/executors/validate-architecture-unchanged/executor.js.map +1 -0
  10. package/architecture/executors/validate-architecture-unchanged/executor.ts +81 -0
  11. package/architecture/executors/validate-architecture-unchanged/schema.json +14 -0
  12. package/architecture/executors/validate-no-cycles/executor.d.ts +16 -0
  13. package/architecture/executors/validate-no-cycles/executor.js +48 -0
  14. package/architecture/executors/validate-no-cycles/executor.js.map +1 -0
  15. package/architecture/executors/validate-no-cycles/executor.ts +60 -0
  16. package/architecture/executors/validate-no-cycles/schema.json +8 -0
  17. package/architecture/executors/validate-no-skiplevel-deps/executor.d.ts +19 -0
  18. package/architecture/executors/validate-no-skiplevel-deps/executor.js +227 -0
  19. package/architecture/executors/validate-no-skiplevel-deps/executor.js.map +1 -0
  20. package/architecture/executors/validate-no-skiplevel-deps/executor.ts +267 -0
  21. package/architecture/executors/validate-no-skiplevel-deps/schema.json +8 -0
  22. package/architecture/executors/visualize/executor.d.ts +17 -0
  23. package/architecture/executors/visualize/executor.js +49 -0
  24. package/architecture/executors/visualize/executor.js.map +1 -0
  25. package/architecture/executors/visualize/executor.ts +63 -0
  26. package/architecture/executors/visualize/schema.json +14 -0
  27. package/architecture/index.d.ts +19 -0
  28. package/architecture/index.js +23 -0
  29. package/architecture/index.js.map +1 -0
  30. package/architecture/index.ts +20 -0
  31. package/architecture/lib/graph-comparator.d.ts +39 -0
  32. package/architecture/lib/graph-comparator.js +100 -0
  33. package/architecture/lib/graph-comparator.js.map +1 -0
  34. package/architecture/lib/graph-comparator.ts +141 -0
  35. package/architecture/lib/graph-generator.d.ts +19 -0
  36. package/architecture/lib/graph-generator.js +88 -0
  37. package/architecture/lib/graph-generator.js.map +1 -0
  38. package/architecture/lib/graph-generator.ts +102 -0
  39. package/architecture/lib/graph-loader.d.ts +31 -0
  40. package/architecture/lib/graph-loader.js +70 -0
  41. package/architecture/lib/graph-loader.js.map +1 -0
  42. package/architecture/lib/graph-loader.ts +82 -0
  43. package/architecture/lib/graph-sorter.d.ts +37 -0
  44. package/architecture/lib/graph-sorter.js +110 -0
  45. package/architecture/lib/graph-sorter.js.map +1 -0
  46. package/architecture/lib/graph-sorter.ts +137 -0
  47. package/architecture/lib/graph-visualizer.d.ts +29 -0
  48. package/architecture/lib/graph-visualizer.js +209 -0
  49. package/architecture/lib/graph-visualizer.js.map +1 -0
  50. package/architecture/lib/graph-visualizer.ts +222 -0
  51. package/architecture/lib/package-validator.d.ts +38 -0
  52. package/architecture/lib/package-validator.js +105 -0
  53. package/architecture/lib/package-validator.js.map +1 -0
  54. package/architecture/lib/package-validator.ts +144 -0
  55. package/config/eslint/base.mjs +6 -0
  56. package/eslint-plugin/__tests__/max-file-lines.test.ts +207 -0
  57. package/eslint-plugin/__tests__/max-method-lines.test.ts +258 -0
  58. package/eslint-plugin/__tests__/no-unmanaged-exceptions.test.ts +359 -0
  59. package/eslint-plugin/index.d.ts +11 -0
  60. package/eslint-plugin/index.js +15 -0
  61. package/eslint-plugin/index.js.map +1 -1
  62. package/eslint-plugin/index.ts +15 -0
  63. package/eslint-plugin/rules/enforce-architecture.d.ts +15 -0
  64. package/eslint-plugin/rules/enforce-architecture.js +406 -0
  65. package/eslint-plugin/rules/enforce-architecture.js.map +1 -0
  66. package/eslint-plugin/rules/enforce-architecture.ts +469 -0
  67. package/eslint-plugin/rules/max-file-lines.d.ts +12 -0
  68. package/eslint-plugin/rules/max-file-lines.js +257 -0
  69. package/eslint-plugin/rules/max-file-lines.js.map +1 -0
  70. package/eslint-plugin/rules/max-file-lines.ts +272 -0
  71. package/eslint-plugin/rules/max-method-lines.d.ts +12 -0
  72. package/eslint-plugin/rules/max-method-lines.js +240 -0
  73. package/eslint-plugin/rules/max-method-lines.js.map +1 -0
  74. package/eslint-plugin/rules/max-method-lines.ts +287 -0
  75. package/eslint-plugin/rules/no-unmanaged-exceptions.d.ts +22 -0
  76. package/eslint-plugin/rules/no-unmanaged-exceptions.js +605 -0
  77. package/eslint-plugin/rules/no-unmanaged-exceptions.js.map +1 -0
  78. package/eslint-plugin/rules/no-unmanaged-exceptions.ts +621 -0
  79. package/executors.json +29 -0
  80. package/generators/init/generator.ts +130 -0
  81. package/generators/init/schema.json +15 -0
  82. package/generators.json +10 -0
  83. package/package.json +20 -3
  84. package/plugin/README.md +236 -0
  85. package/plugin/index.ts +4 -0
package/README.md CHANGED
@@ -6,6 +6,7 @@ Development configuration, scripts, and patterns for WebPieces projects.
6
6
 
7
7
  This package provides shareable development tools for projects using the WebPieces framework:
8
8
 
9
+ - **Nx Plugin** for automatic architecture validation and circular dependency checking
9
10
  - **Executable scripts** for common development tasks
10
11
  - **ESLint configuration** with WebPieces patterns and best practices
11
12
  - **Jest preset** for testing TypeScript projects
@@ -14,6 +15,14 @@ This package provides shareable development tools for projects using the WebPiec
14
15
 
15
16
  ## Installation
16
17
 
18
+ For Nx workspaces (recommended):
19
+
20
+ ```bash
21
+ nx add @webpieces/dev-config
22
+ ```
23
+
24
+ For non-Nx projects:
25
+
17
26
  ```bash
18
27
  npm install --save-dev @webpieces/dev-config
19
28
  ```
@@ -73,7 +82,41 @@ To develop against a local copy of webpieces-ts:
73
82
  wp-use-published
74
83
  ```
75
84
 
76
- ### 2. ESLint Configuration
85
+ ### 2. Nx Plugin (Architecture Validation)
86
+
87
+ Automatically adds architecture validation and circular dependency checking to Nx workspaces.
88
+
89
+ #### Quick Start
90
+
91
+ ```bash
92
+ # Install and register the plugin
93
+ nx add @webpieces/dev-config
94
+
95
+ # Generate dependency graph
96
+ nx run .:arch:generate
97
+
98
+ # Validate architecture
99
+ nx run .:arch:validate-no-cycles
100
+
101
+ # Check project for circular dependencies
102
+ nx run my-project:check-circular-deps
103
+ ```
104
+
105
+ #### Available Targets
106
+
107
+ **Workspace-level:**
108
+ - `arch:generate` - Generate dependency graph
109
+ - `arch:visualize` - Visualize dependency graph
110
+ - `arch:validate-no-cycles` - Validate no circular dependencies
111
+ - `arch:validate-no-skiplevel-deps` - Validate no redundant dependencies
112
+ - `arch:validate-architecture-unchanged` - Validate against blessed graph
113
+
114
+ **Per-project:**
115
+ - `check-circular-deps` - Check for circular dependencies (auto-added to all projects)
116
+
117
+ For detailed documentation, see [Plugin README](./plugin/README.md).
118
+
119
+ ### 3. ESLint Configuration
77
120
 
78
121
  Import the base configuration in your `eslint.config.mjs`:
79
122
 
@@ -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,8 @@
1
+ {
2
+ "$schema": "http://json-schema.org/schema",
3
+ "title": "Validate No Cycles Executor",
4
+ "description": "Validates that the architecture graph has no circular dependencies",
5
+ "type": "object",
6
+ "properties": {},
7
+ "required": []
8
+ }
@@ -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>;