@webpieces/dev-config 0.2.94 → 0.2.97

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 (183) hide show
  1. package/config/eslint/base.mjs +1 -1
  2. package/executors.json +6 -91
  3. package/package.json +6 -19
  4. package/{executors → src/executors}/help/executor.d.ts +4 -2
  5. package/src/executors/help/executor.js.map +1 -0
  6. package/{executors → src/executors}/validate-eslint-sync/executor.d.ts +3 -2
  7. package/src/executors/validate-eslint-sync/executor.js.map +1 -0
  8. package/{executors → src/executors}/validate-versions-locked/executor.js +5 -3
  9. package/src/executors/validate-versions-locked/executor.js.map +1 -0
  10. package/src/generators/init/generator.js.map +1 -1
  11. package/src/index.d.ts +1 -1
  12. package/src/index.js +1 -1
  13. package/src/index.js.map +1 -1
  14. package/src/plugin.d.ts +86 -0
  15. package/{plugin.js → src/plugin.js} +31 -15
  16. package/src/plugin.js.map +1 -0
  17. package/src/toError.d.ts +5 -0
  18. package/src/toError.js +37 -0
  19. package/src/toError.js.map +1 -0
  20. package/templates/eslint.webpieces.config.mjs +1 -1
  21. package/templates/webpieces.exceptions.md +15 -15
  22. package/architecture/executors/diff-utils.d.ts +0 -24
  23. package/architecture/executors/diff-utils.js +0 -119
  24. package/architecture/executors/diff-utils.js.map +0 -1
  25. package/architecture/executors/diff-utils.ts +0 -127
  26. package/architecture/executors/generate/executor.d.ts +0 -16
  27. package/architecture/executors/generate/executor.js +0 -44
  28. package/architecture/executors/generate/executor.js.map +0 -1
  29. package/architecture/executors/generate/executor.ts +0 -59
  30. package/architecture/executors/generate/schema.json +0 -14
  31. package/architecture/executors/validate-architecture-unchanged/executor.d.ts +0 -17
  32. package/architecture/executors/validate-architecture-unchanged/executor.js +0 -229
  33. package/architecture/executors/validate-architecture-unchanged/executor.js.map +0 -1
  34. package/architecture/executors/validate-architecture-unchanged/executor.ts +0 -251
  35. package/architecture/executors/validate-architecture-unchanged/schema.json +0 -14
  36. package/architecture/executors/validate-code/executor.d.ts +0 -78
  37. package/architecture/executors/validate-code/executor.js +0 -243
  38. package/architecture/executors/validate-code/executor.js.map +0 -1
  39. package/architecture/executors/validate-code/executor.ts +0 -406
  40. package/architecture/executors/validate-code/schema.json +0 -227
  41. package/architecture/executors/validate-dtos/executor.d.ts +0 -42
  42. package/architecture/executors/validate-dtos/executor.js +0 -561
  43. package/architecture/executors/validate-dtos/executor.js.map +0 -1
  44. package/architecture/executors/validate-dtos/executor.ts +0 -689
  45. package/architecture/executors/validate-dtos/schema.json +0 -33
  46. package/architecture/executors/validate-modified-files/executor.d.ts +0 -25
  47. package/architecture/executors/validate-modified-files/executor.js +0 -501
  48. package/architecture/executors/validate-modified-files/executor.js.map +0 -1
  49. package/architecture/executors/validate-modified-files/executor.ts +0 -571
  50. package/architecture/executors/validate-modified-files/schema.json +0 -25
  51. package/architecture/executors/validate-modified-methods/executor.d.ts +0 -31
  52. package/architecture/executors/validate-modified-methods/executor.js +0 -694
  53. package/architecture/executors/validate-modified-methods/executor.js.map +0 -1
  54. package/architecture/executors/validate-modified-methods/executor.ts +0 -797
  55. package/architecture/executors/validate-modified-methods/schema.json +0 -25
  56. package/architecture/executors/validate-new-methods/executor.d.ts +0 -28
  57. package/architecture/executors/validate-new-methods/executor.js +0 -513
  58. package/architecture/executors/validate-new-methods/executor.js.map +0 -1
  59. package/architecture/executors/validate-new-methods/executor.ts +0 -584
  60. package/architecture/executors/validate-new-methods/schema.json +0 -25
  61. package/architecture/executors/validate-no-any-unknown/executor.d.ts +0 -42
  62. package/architecture/executors/validate-no-any-unknown/executor.js +0 -462
  63. package/architecture/executors/validate-no-any-unknown/executor.js.map +0 -1
  64. package/architecture/executors/validate-no-any-unknown/executor.ts +0 -540
  65. package/architecture/executors/validate-no-any-unknown/schema.json +0 -24
  66. package/architecture/executors/validate-no-architecture-cycles/executor.d.ts +0 -16
  67. package/architecture/executors/validate-no-architecture-cycles/executor.js +0 -48
  68. package/architecture/executors/validate-no-architecture-cycles/executor.js.map +0 -1
  69. package/architecture/executors/validate-no-architecture-cycles/executor.ts +0 -60
  70. package/architecture/executors/validate-no-architecture-cycles/schema.json +0 -8
  71. package/architecture/executors/validate-no-destructure/executor.d.ts +0 -52
  72. package/architecture/executors/validate-no-destructure/executor.js +0 -491
  73. package/architecture/executors/validate-no-destructure/executor.js.map +0 -1
  74. package/architecture/executors/validate-no-destructure/executor.ts +0 -578
  75. package/architecture/executors/validate-no-destructure/schema.json +0 -24
  76. package/architecture/executors/validate-no-direct-api-resolver/executor.d.ts +0 -47
  77. package/architecture/executors/validate-no-direct-api-resolver/executor.js +0 -566
  78. package/architecture/executors/validate-no-direct-api-resolver/executor.js.map +0 -1
  79. package/architecture/executors/validate-no-direct-api-resolver/executor.ts +0 -666
  80. package/architecture/executors/validate-no-direct-api-resolver/schema.json +0 -29
  81. package/architecture/executors/validate-no-inline-types/executor.d.ts +0 -91
  82. package/architecture/executors/validate-no-inline-types/executor.js +0 -669
  83. package/architecture/executors/validate-no-inline-types/executor.js.map +0 -1
  84. package/architecture/executors/validate-no-inline-types/executor.ts +0 -775
  85. package/architecture/executors/validate-no-inline-types/schema.json +0 -24
  86. package/architecture/executors/validate-no-skiplevel-deps/executor.d.ts +0 -19
  87. package/architecture/executors/validate-no-skiplevel-deps/executor.js +0 -227
  88. package/architecture/executors/validate-no-skiplevel-deps/executor.js.map +0 -1
  89. package/architecture/executors/validate-no-skiplevel-deps/executor.ts +0 -267
  90. package/architecture/executors/validate-no-skiplevel-deps/schema.json +0 -8
  91. package/architecture/executors/validate-packagejson/executor.d.ts +0 -16
  92. package/architecture/executors/validate-packagejson/executor.js +0 -57
  93. package/architecture/executors/validate-packagejson/executor.js.map +0 -1
  94. package/architecture/executors/validate-packagejson/executor.ts +0 -74
  95. package/architecture/executors/validate-packagejson/schema.json +0 -8
  96. package/architecture/executors/validate-prisma-converters/executor.d.ts +0 -60
  97. package/architecture/executors/validate-prisma-converters/executor.js +0 -634
  98. package/architecture/executors/validate-prisma-converters/executor.js.map +0 -1
  99. package/architecture/executors/validate-prisma-converters/executor.ts +0 -822
  100. package/architecture/executors/validate-prisma-converters/schema.json +0 -38
  101. package/architecture/executors/validate-return-types/executor.d.ts +0 -29
  102. package/architecture/executors/validate-return-types/executor.js +0 -439
  103. package/architecture/executors/validate-return-types/executor.js.map +0 -1
  104. package/architecture/executors/validate-return-types/executor.ts +0 -524
  105. package/architecture/executors/validate-return-types/schema.json +0 -24
  106. package/architecture/executors/visualize/executor.d.ts +0 -17
  107. package/architecture/executors/visualize/executor.js +0 -49
  108. package/architecture/executors/visualize/executor.js.map +0 -1
  109. package/architecture/executors/visualize/executor.ts +0 -63
  110. package/architecture/executors/visualize/schema.json +0 -14
  111. package/architecture/index.d.ts +0 -19
  112. package/architecture/index.js +0 -23
  113. package/architecture/index.js.map +0 -1
  114. package/architecture/index.ts +0 -20
  115. package/architecture/lib/graph-comparator.d.ts +0 -39
  116. package/architecture/lib/graph-comparator.js +0 -100
  117. package/architecture/lib/graph-comparator.js.map +0 -1
  118. package/architecture/lib/graph-comparator.ts +0 -141
  119. package/architecture/lib/graph-generator.d.ts +0 -19
  120. package/architecture/lib/graph-generator.js +0 -84
  121. package/architecture/lib/graph-generator.js.map +0 -1
  122. package/architecture/lib/graph-generator.ts +0 -97
  123. package/architecture/lib/graph-loader.d.ts +0 -31
  124. package/architecture/lib/graph-loader.js +0 -98
  125. package/architecture/lib/graph-loader.js.map +0 -1
  126. package/architecture/lib/graph-loader.ts +0 -116
  127. package/architecture/lib/graph-sorter.d.ts +0 -37
  128. package/architecture/lib/graph-sorter.js +0 -110
  129. package/architecture/lib/graph-sorter.js.map +0 -1
  130. package/architecture/lib/graph-sorter.ts +0 -137
  131. package/architecture/lib/graph-visualizer.d.ts +0 -29
  132. package/architecture/lib/graph-visualizer.js +0 -217
  133. package/architecture/lib/graph-visualizer.js.map +0 -1
  134. package/architecture/lib/graph-visualizer.ts +0 -231
  135. package/architecture/lib/package-validator.d.ts +0 -38
  136. package/architecture/lib/package-validator.js +0 -126
  137. package/architecture/lib/package-validator.js.map +0 -1
  138. package/architecture/lib/package-validator.ts +0 -170
  139. package/eslint-plugin/__tests__/catch-error-pattern.test.ts +0 -359
  140. package/eslint-plugin/__tests__/max-file-lines.test.ts +0 -207
  141. package/eslint-plugin/__tests__/max-method-lines.test.ts +0 -258
  142. package/eslint-plugin/__tests__/no-unmanaged-exceptions.test.ts +0 -359
  143. package/eslint-plugin/index.d.ts +0 -23
  144. package/eslint-plugin/index.js +0 -30
  145. package/eslint-plugin/index.js.map +0 -1
  146. package/eslint-plugin/index.ts +0 -29
  147. package/eslint-plugin/rules/catch-error-pattern.d.ts +0 -11
  148. package/eslint-plugin/rules/catch-error-pattern.js +0 -196
  149. package/eslint-plugin/rules/catch-error-pattern.js.map +0 -1
  150. package/eslint-plugin/rules/catch-error-pattern.ts +0 -281
  151. package/eslint-plugin/rules/enforce-architecture.d.ts +0 -15
  152. package/eslint-plugin/rules/enforce-architecture.js +0 -476
  153. package/eslint-plugin/rules/enforce-architecture.js.map +0 -1
  154. package/eslint-plugin/rules/enforce-architecture.ts +0 -543
  155. package/eslint-plugin/rules/max-file-lines.d.ts +0 -12
  156. package/eslint-plugin/rules/max-file-lines.js +0 -257
  157. package/eslint-plugin/rules/max-file-lines.js.map +0 -1
  158. package/eslint-plugin/rules/max-file-lines.ts +0 -272
  159. package/eslint-plugin/rules/max-method-lines.d.ts +0 -12
  160. package/eslint-plugin/rules/max-method-lines.js +0 -240
  161. package/eslint-plugin/rules/max-method-lines.js.map +0 -1
  162. package/eslint-plugin/rules/max-method-lines.ts +0 -287
  163. package/eslint-plugin/rules/no-unmanaged-exceptions.d.ts +0 -22
  164. package/eslint-plugin/rules/no-unmanaged-exceptions.js +0 -160
  165. package/eslint-plugin/rules/no-unmanaged-exceptions.js.map +0 -1
  166. package/eslint-plugin/rules/no-unmanaged-exceptions.ts +0 -179
  167. package/executors/help/executor.js.map +0 -1
  168. package/executors/help/executor.ts +0 -61
  169. package/executors/validate-eslint-sync/executor.js.map +0 -1
  170. package/executors/validate-eslint-sync/executor.ts +0 -83
  171. package/executors/validate-versions-locked/executor.js.map +0 -1
  172. package/executors/validate-versions-locked/executor.ts +0 -367
  173. package/plugin/README.md +0 -243
  174. package/plugin/index.d.ts +0 -4
  175. package/plugin/index.js +0 -8
  176. package/plugin/index.js.map +0 -1
  177. package/plugin/index.ts +0 -4
  178. /package/{executors → src/executors}/help/executor.js +0 -0
  179. /package/{executors → src/executors}/help/schema.json +0 -0
  180. /package/{executors → src/executors}/validate-eslint-sync/executor.js +0 -0
  181. /package/{executors → src/executors}/validate-eslint-sync/schema.json +0 -0
  182. /package/{executors → src/executors}/validate-versions-locked/executor.d.ts +0 -0
  183. /package/{executors → src/executors}/validate-versions-locked/schema.json +0 -0
@@ -1,127 +0,0 @@
1
- /**
2
- * Shared diff utility functions for executor validators.
3
- * These are used by multiple executors for git diff parsing and line-level detection.
4
- */
5
-
6
- import { execSync } from 'child_process';
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
-
10
- /**
11
- * Get the diff content for a specific file.
12
- */
13
- export function getFileDiff(workspaceRoot: string, file: string, base: string, head?: string): string {
14
- try {
15
- const diffTarget = head ? `${base} ${head}` : base;
16
- const diff = execSync(`git diff ${diffTarget} -- "${file}"`, {
17
- cwd: workspaceRoot,
18
- encoding: 'utf-8',
19
- });
20
-
21
- if (!diff && !head) {
22
- const fullPath = path.join(workspaceRoot, file);
23
- if (fs.existsSync(fullPath)) {
24
- const isUntracked = execSync(`git ls-files --others --exclude-standard "${file}"`, {
25
- cwd: workspaceRoot,
26
- encoding: 'utf-8',
27
- }).trim();
28
-
29
- if (isUntracked) {
30
- const content = fs.readFileSync(fullPath, 'utf-8');
31
- const lines = content.split('\n');
32
- return lines.map((line) => `+${line}`).join('\n');
33
- }
34
- }
35
- }
36
-
37
- return diff;
38
- } catch {
39
- return '';
40
- }
41
- }
42
-
43
- /**
44
- * Parse diff to extract changed line numbers (additions only - lines starting with +).
45
- */
46
- export function getChangedLineNumbers(diffContent: string): Set<number> {
47
- const changedLines = new Set<number>();
48
- const lines = diffContent.split('\n');
49
- let currentLine = 0;
50
-
51
- for (const line of lines) {
52
- const hunkMatch = line.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
53
- if (hunkMatch) {
54
- currentLine = parseInt(hunkMatch[1], 10);
55
- continue;
56
- }
57
-
58
- if (line.startsWith('+') && !line.startsWith('+++')) {
59
- changedLines.add(currentLine);
60
- currentLine++;
61
- } else if (line.startsWith('-') && !line.startsWith('---')) {
62
- // Deletions don't increment line number
63
- } else {
64
- currentLine++;
65
- }
66
- }
67
-
68
- return changedLines;
69
- }
70
-
71
- /**
72
- * Parse diff to find newly added method signatures.
73
- */
74
- export function findNewMethodSignaturesInDiff(diffContent: string): Set<string> {
75
- const newMethods = new Set<string>();
76
- const lines = diffContent.split('\n');
77
-
78
- const patterns = [
79
- /^\+\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(/,
80
- /^\+\s*(?:export\s+)?(?:const|let)\s+(\w+)\s*=\s*(?:async\s*)?\(/,
81
- /^\+\s*(?:export\s+)?(?:const|let)\s+(\w+)\s*=\s*(?:async\s+)?function/,
82
- /^\+\s*(?:(?:public|private|protected)\s+)?(?:static\s+)?(?:async\s+)?(\w+)\s*\(/,
83
- ];
84
-
85
- for (const line of lines) {
86
- if (line.startsWith('+') && !line.startsWith('+++')) {
87
- for (const pattern of patterns) {
88
- const match = line.match(pattern);
89
- if (match) {
90
- const methodName = match[1];
91
- if (methodName && !['if', 'for', 'while', 'switch', 'catch', 'constructor'].includes(methodName)) {
92
- newMethods.add(methodName);
93
- }
94
- break;
95
- }
96
- }
97
- }
98
- }
99
-
100
- return newMethods;
101
- }
102
-
103
- /**
104
- * Check if any line in [startLine, endLine] is in the changedLines set.
105
- */
106
- export function hasChangesInRange(startLine: number, endLine: number, changedLines: Set<number>): boolean {
107
- for (let line = startLine; line <= endLine; line++) {
108
- if (changedLines.has(line)) {
109
- return true;
110
- }
111
- }
112
- return false;
113
- }
114
-
115
- /**
116
- * Check if a node (method or function) is new or has changed lines in its range.
117
- */
118
- export function isNewOrModified(
119
- name: string,
120
- startLine: number,
121
- endLine: number,
122
- changedLines: Set<number>,
123
- newMethodNames: Set<string>
124
- ): boolean {
125
- if (newMethodNames.has(name)) return true;
126
- return hasChangesInRange(startLine, endLine, changedLines);
127
- }
@@ -1,16 +0,0 @@
1
- /**
2
- * Generate Executor
3
- *
4
- * Generates the architecture dependency graph and saves it to architecture/dependencies.json.
5
- *
6
- * Usage:
7
- * nx run architecture:generate
8
- */
9
- import type { ExecutorContext } from '@nx/devkit';
10
- export interface GenerateExecutorOptions {
11
- graphPath?: string;
12
- }
13
- export interface ExecutorResult {
14
- success: boolean;
15
- }
16
- export default function runExecutor(options: GenerateExecutorOptions, context: ExecutorContext): Promise<ExecutorResult>;
@@ -1,44 +0,0 @@
1
- "use strict";
2
- /**
3
- * Generate Executor
4
- *
5
- * Generates the architecture dependency graph and saves it to architecture/dependencies.json.
6
- *
7
- * Usage:
8
- * nx run architecture:generate
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.default = runExecutor;
12
- const graph_generator_1 = require("../../lib/graph-generator");
13
- const graph_sorter_1 = require("../../lib/graph-sorter");
14
- const graph_loader_1 = require("../../lib/graph-loader");
15
- async function runExecutor(options, context) {
16
- const { graphPath } = options;
17
- const workspaceRoot = context.root;
18
- console.log('\n📊 Architecture Graph Generator\n');
19
- try {
20
- // Step 1: Generate current graph from project.json files
21
- console.log('📊 Generating dependency graph from project.json files...');
22
- const rawGraph = await (0, graph_generator_1.generateGraph)();
23
- // Step 2: Topological sort (to assign levels for visualization)
24
- console.log('🔄 Computing topological layers...');
25
- const enhancedGraph = (0, graph_sorter_1.sortGraphTopologically)(rawGraph);
26
- // Step 3: Save the graph
27
- console.log('💾 Saving graph to architecture/dependencies.json...');
28
- (0, graph_loader_1.saveGraph)(enhancedGraph, workspaceRoot, graphPath);
29
- console.log('✅ Graph saved successfully');
30
- // Print summary
31
- const projectCount = Object.keys(enhancedGraph).length;
32
- const levels = new Set(Object.values(enhancedGraph).map((e) => e.level));
33
- console.log(`\n📈 Graph Summary:`);
34
- console.log(` Projects: ${projectCount}`);
35
- console.log(` Levels: ${levels.size} (0-${Math.max(...levels)})`);
36
- return { success: true };
37
- }
38
- catch (err) {
39
- const error = err instanceof Error ? err : new Error(String(err));
40
- console.error('❌ Graph generation failed:', error.message);
41
- return { success: false };
42
- }
43
- }
44
- //# sourceMappingURL=executor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/dev-config/architecture/executors/generate/executor.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAeH,8BAoCC;AAhDD,+DAA0D;AAC1D,yDAAgE;AAChE,yDAAmD;AAUpC,KAAK,UAAU,WAAW,CACrC,OAAgC,EAChC,OAAwB;IAExB,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC9B,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAEnC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IAEnD,IAAI,CAAC;QACD,yDAAyD;QACzD,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;QACzE,MAAM,QAAQ,GAAG,MAAM,IAAA,+BAAa,GAAE,CAAC;QAEvC,gEAAgE;QAChE,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAClD,MAAM,aAAa,GAAG,IAAA,qCAAsB,EAAC,QAAQ,CAAC,CAAC;QAEvD,yBAAyB;QACzB,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;QACpE,IAAA,wBAAS,EAAC,aAAa,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAE1C,gBAAgB;QAChB,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,gBAAgB,YAAY,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,IAAI,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAEpE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC7B,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 * Generate Executor\n *\n * Generates the architecture dependency graph and saves it to architecture/dependencies.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 { 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 (to assign levels for visualization)\n console.log('🔄 Computing topological layers...');\n const enhancedGraph = sortGraphTopologically(rawGraph);\n\n // Step 3: 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"]}
@@ -1,59 +0,0 @@
1
- /**
2
- * Generate Executor
3
- *
4
- * Generates the architecture dependency graph and saves it to architecture/dependencies.json.
5
- *
6
- * Usage:
7
- * nx run architecture:generate
8
- */
9
-
10
- import type { ExecutorContext } from '@nx/devkit';
11
- import { generateGraph } from '../../lib/graph-generator';
12
- import { sortGraphTopologically } from '../../lib/graph-sorter';
13
- import { saveGraph } from '../../lib/graph-loader';
14
-
15
- export interface GenerateExecutorOptions {
16
- graphPath?: string;
17
- }
18
-
19
- export interface ExecutorResult {
20
- success: boolean;
21
- }
22
-
23
- export default async function runExecutor(
24
- options: GenerateExecutorOptions,
25
- context: ExecutorContext
26
- ): Promise<ExecutorResult> {
27
- const { graphPath } = options;
28
- const workspaceRoot = context.root;
29
-
30
- console.log('\n📊 Architecture Graph Generator\n');
31
-
32
- try {
33
- // Step 1: Generate current graph from project.json files
34
- console.log('📊 Generating dependency graph from project.json files...');
35
- const rawGraph = await generateGraph();
36
-
37
- // Step 2: Topological sort (to assign levels for visualization)
38
- console.log('🔄 Computing topological layers...');
39
- const enhancedGraph = sortGraphTopologically(rawGraph);
40
-
41
- // Step 3: Save the graph
42
- console.log('💾 Saving graph to architecture/dependencies.json...');
43
- saveGraph(enhancedGraph, workspaceRoot, graphPath);
44
- console.log('✅ Graph saved successfully');
45
-
46
- // Print summary
47
- const projectCount = Object.keys(enhancedGraph).length;
48
- const levels = new Set(Object.values(enhancedGraph).map((e) => e.level));
49
- console.log(`\n📈 Graph Summary:`);
50
- console.log(` Projects: ${projectCount}`);
51
- console.log(` Levels: ${levels.size} (0-${Math.max(...levels)})`);
52
-
53
- return { success: true };
54
- } catch (err: unknown) {
55
- const error = err instanceof Error ? err : new Error(String(err));
56
- console.error('❌ Graph generation failed:', error.message);
57
- return { success: false };
58
- }
59
- }
@@ -1,14 +0,0 @@
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
- }
@@ -1,17 +0,0 @@
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>;
@@ -1,229 +0,0 @@
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 tslib_1 = require("tslib");
14
- const fs = tslib_1.__importStar(require("fs"));
15
- const path = tslib_1.__importStar(require("path"));
16
- const graph_generator_1 = require("../../lib/graph-generator");
17
- const graph_sorter_1 = require("../../lib/graph-sorter");
18
- const graph_comparator_1 = require("../../lib/graph-comparator");
19
- const graph_loader_1 = require("../../lib/graph-loader");
20
- const TMP_DIR = 'tmp/webpieces';
21
- const TMP_MD_FILE = 'webpieces.dependencies.md';
22
- const DEPENDENCIES_DOC_CONTENT = `# Instructions: Architecture Dependency Violation
23
-
24
- IN GENERAL, it is better to avoid these changes and find a different way by moving classes
25
- around to existing packages you already depend on. It is not always avoidable though.
26
- A clean dependency graph keeps you out of huge trouble later.
27
-
28
- If you are a human, simply run these commands:
29
- * nx run architecture:visualize - to see the new dependencies and validate that change is desired
30
- * nx run architecture:generate - updates the dep graph
31
- * git diff architecture/dependencies.json - to see the deps changes you made
32
-
33
- **READ THIS FILE FIRST before making any changes!**
34
-
35
- ## ⚠️ CRITICAL WARNING ⚠️
36
-
37
- **This is a VERY IMPORTANT change that has LARGE REPERCUSSIONS later!**
38
-
39
- Adding new dependencies creates technical debt that compounds over time:
40
- - Creates coupling between packages that may be hard to undo
41
- - Can create circular dependency tangles
42
- - Makes packages harder to test in isolation
43
- - Increases build times and bundle sizes
44
- - May force unnecessary upgrades across the codebase
45
-
46
- **DO NOT add dependencies without senior developer approval!**
47
-
48
- ## Understanding the Error
49
-
50
- You've attempted to import from a package that is not in your project's allowed dependencies.
51
- The architecture enforces a layered dependency structure where:
52
- - Level 0 packages are foundation packages with NO dependencies on other @webpieces packages
53
- - Higher level packages can only depend on lower level packages
54
- - All dependencies must be explicitly declared
55
-
56
- ## Steps to Resolve
57
-
58
- ### Step 1: Generate Current Dependency Graph
59
- Run this command to see the current architecture:
60
- \`\`\`bash
61
- npx nx run architecture:generate
62
- \`\`\`
63
- This creates/updates \`architecture/dependencies.json\` showing all packages and their levels.
64
-
65
- ### Step 2: Analyze the Proposed Change
66
- Ask yourself:
67
- 1. **Is this import truly necessary?** Can you refactor to avoid it?
68
- 2. **Should the code move instead?** Maybe the code belongs in a different package.
69
- 3. **Will this create a cycle?** Use \`npx nx graph\` to visualize dependencies.
70
- 4. **Can you use an interface/abstraction?** Define interface in lower-level package, implement in higher-level.
71
-
72
- ### Step 3: Get Senior Developer Approval
73
-
74
- ## 🛑 AI AGENTS: STOP HERE AND ASK FOR HUMAN APPROVAL! 🛑
75
-
76
- **YOU MUST NOT PROCEED TO STEP 4 WITHOUT EXPLICIT HUMAN APPROVAL!**
77
-
78
- **REQUIRED**: Discuss this architectural change with a senior developer before proceeding.
79
- - Explain why the dependency is needed
80
- - Show you've considered alternatives (Step 2)
81
- - **WAIT for explicit approval before making ANY changes to project.json or package.json**
82
-
83
- **AI Agent Instructions:**
84
- 1. Present your analysis from Step 2 to the human
85
- 2. Explain which package needs which dependency and why
86
- 3. ASK: "Do you approve adding this dependency?"
87
- 4. **DO NOT modify project.json or package.json until you receive explicit "yes" or approval**
88
-
89
- ### Step 4: If Approved, Add the Dependency
90
-
91
- ## ⛔ NEVER MODIFY THESE FILES WITHOUT HUMAN APPROVAL FROM STEP 3! ⛔
92
-
93
- Only after receiving explicit human approval in Step 3, make these changes:
94
-
95
- 1. **Update project.json** - Add to \`build.dependsOn\`:
96
- \`\`\`json
97
- {
98
- "targets": {
99
- "build": {
100
- "dependsOn": ["^build", "dep1:build", "NEW_PACKAGE:build"]
101
- }
102
- }
103
- }
104
- \`\`\`
105
-
106
- 2. **Update package.json** - Add to \`dependencies\`:
107
- \`\`\`json
108
- {
109
- "dependencies": {
110
- "@webpieces/NEW_PACKAGE": "*"
111
- }
112
- }
113
- \`\`\`
114
-
115
- ### Step 5: Update Architecture Definition
116
- Run this command to validate and update the architecture:
117
- \`\`\`bash
118
- npx nx run architecture:generate
119
- \`\`\`
120
-
121
- This will:
122
- - Detect any cycles (which MUST be fixed before proceeding)
123
- - Update \`architecture/dependencies.json\` with the new dependency
124
- - Recalculate package levels
125
-
126
- ### Step 6: Verify No Cycles
127
- \`\`\`bash
128
- npx nx run architecture:validate-no-architecture-cycles
129
- \`\`\`
130
-
131
- If cycles are detected, you MUST refactor to break the cycle. Common strategies:
132
- - Move shared code to a lower-level package
133
- - Use dependency inversion (interfaces in low-level, implementations in high-level)
134
- - Restructure package boundaries
135
-
136
- ## Alternative Solutions (Preferred over adding dependencies)
137
-
138
- ### Option A: Move the Code
139
- If you need functionality from another package, consider moving that code to a shared lower-level package.
140
-
141
- ### Option B: Dependency Inversion
142
- Define an interface in the lower-level package, implement it in the higher-level package:
143
- \`\`\`typescript
144
- // In foundation package (level 0)
145
- export interface Logger { log(msg: string): void; }
146
-
147
- // In higher-level package
148
- export class ConsoleLogger implements Logger { ... }
149
- \`\`\`
150
-
151
- ### Option C: Pass Dependencies as Parameters
152
- Instead of importing, receive the dependency as a constructor or method parameter.
153
-
154
- ## Remember
155
- - Every dependency you add today is technical debt for tomorrow
156
- - The best dependency is the one you don't need
157
- - When in doubt, refactor rather than add dependencies
158
- `;
159
- /**
160
- * Write the instructions documentation to tmp directory
161
- */
162
- function writeTmpInstructionsFile(workspaceRoot) {
163
- const tmpDir = path.join(workspaceRoot, TMP_DIR);
164
- const mdPath = path.join(tmpDir, TMP_MD_FILE);
165
- // Ensure tmp directory exists
166
- fs.mkdirSync(tmpDir, { recursive: true });
167
- // Write documentation MD file
168
- fs.writeFileSync(mdPath, DEPENDENCIES_DOC_CONTENT);
169
- return mdPath;
170
- }
171
- async function runExecutor(options, context) {
172
- const { graphPath } = options;
173
- const workspaceRoot = context.root;
174
- console.log('\n🔍 Validating Architecture Unchanged\n');
175
- try {
176
- // Check if saved graph exists
177
- if (!(0, graph_loader_1.graphFileExists)(workspaceRoot, graphPath)) {
178
- console.error('❌ No saved graph found at architecture/dependencies.json');
179
- console.error('');
180
- console.error('To initialize:');
181
- console.error(' 1. Run: nx run architecture:generate');
182
- console.error(' 2. Run: nx run architecture:visualize');
183
- console.error(' 3. Manually inspect the generated graph to confirm it is the desired architecture');
184
- console.error(' 4. Commit architecture/dependencies.json');
185
- return { success: false };
186
- }
187
- // Step 1: Generate current graph from project.json files
188
- console.log('📊 Generating current dependency graph...');
189
- const rawGraph = await (0, graph_generator_1.generateGraph)();
190
- // Step 2: Topological sort (to get enhanced graph with levels)
191
- console.log('🔄 Computing topological layers...');
192
- const currentGraph = (0, graph_sorter_1.sortGraphTopologically)(rawGraph);
193
- // Step 3: Load saved graph
194
- console.log('📂 Loading saved graph...');
195
- const savedGraph = (0, graph_loader_1.loadBlessedGraph)(workspaceRoot, graphPath);
196
- if (!savedGraph) {
197
- console.error('❌ Could not load saved graph');
198
- return { success: false };
199
- }
200
- // Step 4: Compare graphs
201
- console.log('🔍 Comparing current graph to saved graph...');
202
- const comparison = (0, graph_comparator_1.compareGraphs)(currentGraph, savedGraph);
203
- if (comparison.identical) {
204
- console.log('✅ Architecture unchanged - current graph matches saved graph');
205
- return { success: true };
206
- }
207
- else {
208
- // Write instructions file for AI agent
209
- const mdPath = writeTmpInstructionsFile(workspaceRoot);
210
- console.error('❌ Architecture has changed since last update!');
211
- console.error('\nDifferences:');
212
- console.error(comparison.summary);
213
- console.error('');
214
- console.error('⚠️ *** Refer to ' + mdPath + ' for instructions on how to fix *** ⚠️');
215
- console.error('');
216
- console.error('To fix:');
217
- console.error(' 1. Review the changes above');
218
- console.error(' 2. If intentional, ASK USER to run: nx run architecture:generate since this is a critical change');
219
- console.error(' 3. Commit the updated architecture/dependencies.json');
220
- return { success: false };
221
- }
222
- }
223
- catch (err) {
224
- const error = err instanceof Error ? err : new Error(String(err));
225
- console.error('❌ Architecture validation failed:', error.message);
226
- return { success: false };
227
- }
228
- }
229
- //# sourceMappingURL=executor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/dev-config/architecture/executors/validate-architecture-unchanged/executor.ts"],"names":[],"mappings":"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","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 * as fs from 'fs';\nimport * as path from 'path';\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\nconst TMP_DIR = 'tmp/webpieces';\nconst TMP_MD_FILE = 'webpieces.dependencies.md';\n\nconst DEPENDENCIES_DOC_CONTENT = `# Instructions: Architecture Dependency Violation\n\nIN GENERAL, it is better to avoid these changes and find a different way by moving classes\naround to existing packages you already depend on. It is not always avoidable though.\nA clean dependency graph keeps you out of huge trouble later.\n\nIf you are a human, simply run these commands:\n* nx run architecture:visualize - to see the new dependencies and validate that change is desired\n* nx run architecture:generate - updates the dep graph\n* git diff architecture/dependencies.json - to see the deps changes you made\n\n**READ THIS FILE FIRST before making any changes!**\n\n## ⚠️ CRITICAL WARNING ⚠️\n\n**This is a VERY IMPORTANT change that has LARGE REPERCUSSIONS later!**\n\nAdding new dependencies creates technical debt that compounds over time:\n- Creates coupling between packages that may be hard to undo\n- Can create circular dependency tangles\n- Makes packages harder to test in isolation\n- Increases build times and bundle sizes\n- May force unnecessary upgrades across the codebase\n\n**DO NOT add dependencies without senior developer approval!**\n\n## Understanding the Error\n\nYou've attempted to import from a package that is not in your project's allowed dependencies.\nThe architecture enforces a layered dependency structure where:\n- Level 0 packages are foundation packages with NO dependencies on other @webpieces packages\n- Higher level packages can only depend on lower level packages\n- All dependencies must be explicitly declared\n\n## Steps to Resolve\n\n### Step 1: Generate Current Dependency Graph\nRun this command to see the current architecture:\n\\`\\`\\`bash\nnpx nx run architecture:generate\n\\`\\`\\`\nThis creates/updates \\`architecture/dependencies.json\\` showing all packages and their levels.\n\n### Step 2: Analyze the Proposed Change\nAsk yourself:\n1. **Is this import truly necessary?** Can you refactor to avoid it?\n2. **Should the code move instead?** Maybe the code belongs in a different package.\n3. **Will this create a cycle?** Use \\`npx nx graph\\` to visualize dependencies.\n4. **Can you use an interface/abstraction?** Define interface in lower-level package, implement in higher-level.\n\n### Step 3: Get Senior Developer Approval\n\n## 🛑 AI AGENTS: STOP HERE AND ASK FOR HUMAN APPROVAL! 🛑\n\n**YOU MUST NOT PROCEED TO STEP 4 WITHOUT EXPLICIT HUMAN APPROVAL!**\n\n**REQUIRED**: Discuss this architectural change with a senior developer before proceeding.\n- Explain why the dependency is needed\n- Show you've considered alternatives (Step 2)\n- **WAIT for explicit approval before making ANY changes to project.json or package.json**\n\n**AI Agent Instructions:**\n1. Present your analysis from Step 2 to the human\n2. Explain which package needs which dependency and why\n3. ASK: \"Do you approve adding this dependency?\"\n4. **DO NOT modify project.json or package.json until you receive explicit \"yes\" or approval**\n\n### Step 4: If Approved, Add the Dependency\n\n## ⛔ NEVER MODIFY THESE FILES WITHOUT HUMAN APPROVAL FROM STEP 3! ⛔\n\nOnly after receiving explicit human approval in Step 3, make these changes:\n\n1. **Update project.json** - Add to \\`build.dependsOn\\`:\n \\`\\`\\`json\n {\n \"targets\": {\n \"build\": {\n \"dependsOn\": [\"^build\", \"dep1:build\", \"NEW_PACKAGE:build\"]\n }\n }\n }\n \\`\\`\\`\n\n2. **Update package.json** - Add to \\`dependencies\\`:\n \\`\\`\\`json\n {\n \"dependencies\": {\n \"@webpieces/NEW_PACKAGE\": \"*\"\n }\n }\n \\`\\`\\`\n\n### Step 5: Update Architecture Definition\nRun this command to validate and update the architecture:\n\\`\\`\\`bash\nnpx nx run architecture:generate\n\\`\\`\\`\n\nThis will:\n- Detect any cycles (which MUST be fixed before proceeding)\n- Update \\`architecture/dependencies.json\\` with the new dependency\n- Recalculate package levels\n\n### Step 6: Verify No Cycles\n\\`\\`\\`bash\nnpx nx run architecture:validate-no-architecture-cycles\n\\`\\`\\`\n\nIf cycles are detected, you MUST refactor to break the cycle. Common strategies:\n- Move shared code to a lower-level package\n- Use dependency inversion (interfaces in low-level, implementations in high-level)\n- Restructure package boundaries\n\n## Alternative Solutions (Preferred over adding dependencies)\n\n### Option A: Move the Code\nIf you need functionality from another package, consider moving that code to a shared lower-level package.\n\n### Option B: Dependency Inversion\nDefine an interface in the lower-level package, implement it in the higher-level package:\n\\`\\`\\`typescript\n// In foundation package (level 0)\nexport interface Logger { log(msg: string): void; }\n\n// In higher-level package\nexport class ConsoleLogger implements Logger { ... }\n\\`\\`\\`\n\n### Option C: Pass Dependencies as Parameters\nInstead of importing, receive the dependency as a constructor or method parameter.\n\n## Remember\n- Every dependency you add today is technical debt for tomorrow\n- The best dependency is the one you don't need\n- When in doubt, refactor rather than add dependencies\n`;\n\n/**\n * Write the instructions documentation to tmp directory\n */\nfunction writeTmpInstructionsFile(workspaceRoot: string): string {\n const tmpDir = path.join(workspaceRoot, TMP_DIR);\n const mdPath = path.join(tmpDir, TMP_MD_FILE);\n\n // Ensure tmp directory exists\n fs.mkdirSync(tmpDir, { recursive: true });\n\n // Write documentation MD file\n fs.writeFileSync(mdPath, DEPENDENCIES_DOC_CONTENT);\n\n return mdPath;\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('');\n console.error('To initialize:');\n console.error(' 1. Run: nx run architecture:generate');\n console.error(' 2. Run: nx run architecture:visualize');\n console.error(' 3. Manually inspect the generated graph to confirm it is the desired architecture');\n console.error(' 4. Commit architecture/dependencies.json');\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 // Write instructions file for AI agent\n const mdPath = writeTmpInstructionsFile(workspaceRoot);\n\n console.error('❌ Architecture has changed since last update!');\n console.error('\\nDifferences:');\n console.error(comparison.summary);\n console.error('');\n console.error('⚠️ *** Refer to ' + mdPath + ' for instructions on how to fix *** ⚠️');\n console.error('');\n console.error('To fix:');\n console.error(' 1. Review the changes above');\n console.error(' 2. If intentional, ASK USER to run: nx run architecture:generate since this is a critical change');\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"]}