@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,98 +0,0 @@
1
- "use strict";
2
- /**
3
- * Graph Loader
4
- *
5
- * Handles loading and saving the blessed dependency graph file.
6
- * The graph is stored at architecture/dependencies.json in the workspace root.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.DEFAULT_GRAPH_PATH = void 0;
10
- exports.loadBlessedGraph = loadBlessedGraph;
11
- exports.saveGraph = saveGraph;
12
- exports.graphFileExists = graphFileExists;
13
- const tslib_1 = require("tslib");
14
- const fs = tslib_1.__importStar(require("fs"));
15
- const path = tslib_1.__importStar(require("path"));
16
- /**
17
- * Default path for the dependencies file (relative to workspace root)
18
- */
19
- exports.DEFAULT_GRAPH_PATH = 'architecture/dependencies.json';
20
- /**
21
- * Load the blessed graph from disk
22
- *
23
- * @param workspaceRoot - Absolute path to workspace root
24
- * @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)
25
- * @returns The blessed graph, or null if file doesn't exist
26
- */
27
- function loadBlessedGraph(workspaceRoot, graphPath = exports.DEFAULT_GRAPH_PATH) {
28
- const fullPath = path.join(workspaceRoot, graphPath);
29
- if (!fs.existsSync(fullPath)) {
30
- return null;
31
- }
32
- try {
33
- const content = fs.readFileSync(fullPath, 'utf-8');
34
- return JSON.parse(content);
35
- }
36
- catch (err) {
37
- throw new Error(`Failed to load graph from ${fullPath}: ${err}`);
38
- }
39
- }
40
- /**
41
- * Format a graph as JSON with multi-line arrays for readability
42
- */
43
- function formatGraphJson(graph) {
44
- const lines = ['{'];
45
- const keys = Object.keys(graph).sort();
46
- keys.forEach((key, index) => {
47
- const entry = graph[key];
48
- const isLast = index === keys.length - 1;
49
- const comma = isLast ? '' : ',';
50
- lines.push(` "${key}": {`);
51
- lines.push(` "level": ${entry.level},`);
52
- if (entry.dependsOn.length === 0) {
53
- lines.push(` "dependsOn": []`);
54
- }
55
- else {
56
- lines.push(` "dependsOn": [`);
57
- entry.dependsOn.forEach((dep, depIndex) => {
58
- const depComma = depIndex === entry.dependsOn.length - 1 ? '' : ',';
59
- lines.push(` "${dep}"${depComma}`);
60
- });
61
- lines.push(` ]`);
62
- }
63
- lines.push(` }${comma}`);
64
- });
65
- lines.push('}');
66
- return lines.join('\n') + '\n';
67
- }
68
- /**
69
- * Save the graph to disk
70
- *
71
- * @param graph - The graph to save
72
- * @param workspaceRoot - Absolute path to workspace root
73
- * @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)
74
- */
75
- function saveGraph(graph, workspaceRoot, graphPath = exports.DEFAULT_GRAPH_PATH) {
76
- const fullPath = path.join(workspaceRoot, graphPath);
77
- const dir = path.dirname(fullPath);
78
- // Ensure directory exists
79
- if (!fs.existsSync(dir)) {
80
- fs.mkdirSync(dir, { recursive: true });
81
- }
82
- // Sort keys for deterministic output
83
- const sortedGraph = {};
84
- const sortedKeys = Object.keys(graph).sort();
85
- for (const key of sortedKeys) {
86
- sortedGraph[key] = graph[key];
87
- }
88
- const content = formatGraphJson(sortedGraph);
89
- fs.writeFileSync(fullPath, content, 'utf-8');
90
- }
91
- /**
92
- * Check if the graph file exists
93
- */
94
- function graphFileExists(workspaceRoot, graphPath = exports.DEFAULT_GRAPH_PATH) {
95
- const fullPath = path.join(workspaceRoot, graphPath);
96
- return fs.existsSync(fullPath);
97
- }
98
- //# sourceMappingURL=graph-loader.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"graph-loader.js","sourceRoot":"","sources":["../../../../../../packages/tooling/dev-config/architecture/lib/graph-loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Graph Loader\n *\n * Handles loading and saving the blessed dependency graph file.\n * The graph is stored at architecture/dependencies.json in the workspace root.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { EnhancedGraph } from './graph-sorter';\n\n/**\n * Default path for the dependencies file (relative to workspace root)\n */\nexport const DEFAULT_GRAPH_PATH = 'architecture/dependencies.json';\n\n/**\n * Load the blessed graph from disk\n *\n * @param workspaceRoot - Absolute path to workspace root\n * @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)\n * @returns The blessed graph, or null if file doesn't exist\n */\nexport function loadBlessedGraph(\n workspaceRoot: string,\n graphPath: string = DEFAULT_GRAPH_PATH\n): EnhancedGraph | null {\n const fullPath = path.join(workspaceRoot, graphPath);\n\n if (!fs.existsSync(fullPath)) {\n return null;\n }\n\n try {\n const content = fs.readFileSync(fullPath, 'utf-8');\n return JSON.parse(content) as EnhancedGraph;\n } catch (err: unknown) {\n throw new Error(`Failed to load graph from ${fullPath}: ${err}`);\n }\n}\n\n/**\n * Format a graph as JSON with multi-line arrays for readability\n */\nfunction formatGraphJson(graph: EnhancedGraph): string {\n const lines: string[] = ['{'];\n const keys = Object.keys(graph).sort();\n\n keys.forEach((key, index) => {\n const entry = graph[key];\n const isLast = index === keys.length - 1;\n const comma = isLast ? '' : ',';\n\n lines.push(` \"${key}\": {`);\n lines.push(` \"level\": ${entry.level},`);\n\n if (entry.dependsOn.length === 0) {\n lines.push(` \"dependsOn\": []`);\n } else {\n lines.push(` \"dependsOn\": [`);\n entry.dependsOn.forEach((dep, depIndex) => {\n const depComma = depIndex === entry.dependsOn.length - 1 ? '' : ',';\n lines.push(` \"${dep}\"${depComma}`);\n });\n lines.push(` ]`);\n }\n\n lines.push(` }${comma}`);\n\n });\n\n lines.push('}');\n return lines.join('\\n') + '\\n';\n}\n\n/**\n * Save the graph to disk\n *\n * @param graph - The graph to save\n * @param workspaceRoot - Absolute path to workspace root\n * @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)\n */\nexport function saveGraph(\n graph: EnhancedGraph,\n workspaceRoot: string,\n graphPath: string = DEFAULT_GRAPH_PATH\n): void {\n const fullPath = path.join(workspaceRoot, graphPath);\n const dir = path.dirname(fullPath);\n\n // Ensure directory exists\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Sort keys for deterministic output\n const sortedGraph: EnhancedGraph = {};\n const sortedKeys = Object.keys(graph).sort();\n for (const key of sortedKeys) {\n sortedGraph[key] = graph[key];\n }\n\n const content = formatGraphJson(sortedGraph);\n fs.writeFileSync(fullPath, content, 'utf-8');\n}\n\n/**\n * Check if the graph file exists\n */\nexport function graphFileExists(\n workspaceRoot: string,\n graphPath: string = DEFAULT_GRAPH_PATH\n): boolean {\n const fullPath = path.join(workspaceRoot, graphPath);\n return fs.existsSync(fullPath);\n}\n"]}
@@ -1,116 +0,0 @@
1
- /**
2
- * Graph Loader
3
- *
4
- * Handles loading and saving the blessed dependency graph file.
5
- * The graph is stored at architecture/dependencies.json in the workspace root.
6
- */
7
-
8
- import * as fs from 'fs';
9
- import * as path from 'path';
10
- import type { EnhancedGraph } from './graph-sorter';
11
-
12
- /**
13
- * Default path for the dependencies file (relative to workspace root)
14
- */
15
- export const DEFAULT_GRAPH_PATH = 'architecture/dependencies.json';
16
-
17
- /**
18
- * Load the blessed graph from disk
19
- *
20
- * @param workspaceRoot - Absolute path to workspace root
21
- * @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)
22
- * @returns The blessed graph, or null if file doesn't exist
23
- */
24
- export function loadBlessedGraph(
25
- workspaceRoot: string,
26
- graphPath: string = DEFAULT_GRAPH_PATH
27
- ): EnhancedGraph | null {
28
- const fullPath = path.join(workspaceRoot, graphPath);
29
-
30
- if (!fs.existsSync(fullPath)) {
31
- return null;
32
- }
33
-
34
- try {
35
- const content = fs.readFileSync(fullPath, 'utf-8');
36
- return JSON.parse(content) as EnhancedGraph;
37
- } catch (err: unknown) {
38
- throw new Error(`Failed to load graph from ${fullPath}: ${err}`);
39
- }
40
- }
41
-
42
- /**
43
- * Format a graph as JSON with multi-line arrays for readability
44
- */
45
- function formatGraphJson(graph: EnhancedGraph): string {
46
- const lines: string[] = ['{'];
47
- const keys = Object.keys(graph).sort();
48
-
49
- keys.forEach((key, index) => {
50
- const entry = graph[key];
51
- const isLast = index === keys.length - 1;
52
- const comma = isLast ? '' : ',';
53
-
54
- lines.push(` "${key}": {`);
55
- lines.push(` "level": ${entry.level},`);
56
-
57
- if (entry.dependsOn.length === 0) {
58
- lines.push(` "dependsOn": []`);
59
- } else {
60
- lines.push(` "dependsOn": [`);
61
- entry.dependsOn.forEach((dep, depIndex) => {
62
- const depComma = depIndex === entry.dependsOn.length - 1 ? '' : ',';
63
- lines.push(` "${dep}"${depComma}`);
64
- });
65
- lines.push(` ]`);
66
- }
67
-
68
- lines.push(` }${comma}`);
69
-
70
- });
71
-
72
- lines.push('}');
73
- return lines.join('\n') + '\n';
74
- }
75
-
76
- /**
77
- * Save the graph to disk
78
- *
79
- * @param graph - The graph to save
80
- * @param workspaceRoot - Absolute path to workspace root
81
- * @param graphPath - Relative path to graph file (default: .graphs/dependencies.json)
82
- */
83
- export function saveGraph(
84
- graph: EnhancedGraph,
85
- workspaceRoot: string,
86
- graphPath: string = DEFAULT_GRAPH_PATH
87
- ): void {
88
- const fullPath = path.join(workspaceRoot, graphPath);
89
- const dir = path.dirname(fullPath);
90
-
91
- // Ensure directory exists
92
- if (!fs.existsSync(dir)) {
93
- fs.mkdirSync(dir, { recursive: true });
94
- }
95
-
96
- // Sort keys for deterministic output
97
- const sortedGraph: EnhancedGraph = {};
98
- const sortedKeys = Object.keys(graph).sort();
99
- for (const key of sortedKeys) {
100
- sortedGraph[key] = graph[key];
101
- }
102
-
103
- const content = formatGraphJson(sortedGraph);
104
- fs.writeFileSync(fullPath, content, 'utf-8');
105
- }
106
-
107
- /**
108
- * Check if the graph file exists
109
- */
110
- export function graphFileExists(
111
- workspaceRoot: string,
112
- graphPath: string = DEFAULT_GRAPH_PATH
113
- ): boolean {
114
- const fullPath = path.join(workspaceRoot, graphPath);
115
- return fs.existsSync(fullPath);
116
- }
@@ -1,37 +0,0 @@
1
- /**
2
- * Graph Sorter
3
- *
4
- * Performs topological sorting on the dependency graph to:
5
- * 1. Detect circular dependencies (fails if cycle found)
6
- * 2. Assign level numbers to each project (level 0 = no deps, level 1 = depends on level 0, etc.)
7
- * 3. Group projects into layers for deterministic ordering
8
- */
9
- /**
10
- * Graph entry with level metadata
11
- */
12
- export interface GraphEntry {
13
- level: number;
14
- dependsOn: string[];
15
- }
16
- /**
17
- * Enhanced graph format with level information
18
- */
19
- export type EnhancedGraph = Record<string, GraphEntry>;
20
- /**
21
- * Compute topological layers for dependency graph using Kahn's algorithm
22
- *
23
- * Projects are grouped into layers where each layer only depends on previous layers.
24
- * Throws an error if a circular dependency is detected.
25
- *
26
- * @param graph - Dependency graph { project: [deps] }
27
- * @returns Array of layers, each containing sorted project names
28
- */
29
- export declare function computeTopologicalLayers(graph: Record<string, string[]>): string[][];
30
- /**
31
- * Sort graph in topological order with alphabetical sorting within layers
32
- * Returns enhanced format with level metadata
33
- *
34
- * @param graph - Unsorted dependency graph { project: [deps] }
35
- * @returns Sorted graph with level metadata { project: { level: number, dependsOn: [deps] } }
36
- */
37
- export declare function sortGraphTopologically(graph: Record<string, string[]>): EnhancedGraph;
@@ -1,110 +0,0 @@
1
- "use strict";
2
- /**
3
- * Graph Sorter
4
- *
5
- * Performs topological sorting on the dependency graph to:
6
- * 1. Detect circular dependencies (fails if cycle found)
7
- * 2. Assign level numbers to each project (level 0 = no deps, level 1 = depends on level 0, etc.)
8
- * 3. Group projects into layers for deterministic ordering
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.computeTopologicalLayers = computeTopologicalLayers;
12
- exports.sortGraphTopologically = sortGraphTopologically;
13
- /**
14
- * Compute topological layers for dependency graph using Kahn's algorithm
15
- *
16
- * Projects are grouped into layers where each layer only depends on previous layers.
17
- * Throws an error if a circular dependency is detected.
18
- *
19
- * @param graph - Dependency graph { project: [deps] }
20
- * @returns Array of layers, each containing sorted project names
21
- */
22
- function computeTopologicalLayers(graph) {
23
- const layers = [];
24
- const processed = new Set();
25
- const allProjects = Object.keys(graph);
26
- while (processed.size < allProjects.length) {
27
- const currentLayer = [];
28
- for (const project of allProjects) {
29
- if (processed.has(project))
30
- continue;
31
- const deps = graph[project] || [];
32
- // Check if all dependencies are in previous layers (already processed)
33
- const allDepsInPrevLayers = deps.every((dep) => processed.has(dep));
34
- if (allDepsInPrevLayers) {
35
- currentLayer.push(project);
36
- }
37
- }
38
- if (currentLayer.length === 0) {
39
- // No progress made = circular dependency detected
40
- const remaining = allProjects.filter((p) => !processed.has(p));
41
- // Try to identify the cycle
42
- const cycleInfo = findCycle(graph, remaining);
43
- throw new Error(`Circular dependency detected among: ${remaining.join(', ')}\n` +
44
- (cycleInfo ? `Cycle: ${cycleInfo}\n` : '') +
45
- 'Fix: Remove one of the dependencies to break the cycle.');
46
- }
47
- // Sort alphabetically within layer for deterministic output
48
- currentLayer.sort();
49
- layers.push(currentLayer);
50
- // Mark as processed
51
- currentLayer.forEach((p) => processed.add(p));
52
- }
53
- return layers;
54
- }
55
- /**
56
- * Try to find and describe a cycle in the graph
57
- */
58
- function findCycle(graph, remaining) {
59
- const visited = new Set();
60
- const path = [];
61
- function dfs(node) {
62
- if (path.includes(node)) {
63
- const cycleStart = path.indexOf(node);
64
- return [...path.slice(cycleStart), node].join(' -> ');
65
- }
66
- if (visited.has(node))
67
- return null;
68
- visited.add(node);
69
- path.push(node);
70
- const deps = graph[node] || [];
71
- for (const dep of deps) {
72
- if (remaining.includes(dep)) {
73
- const result = dfs(dep);
74
- if (result)
75
- return result;
76
- }
77
- }
78
- path.pop();
79
- return null;
80
- }
81
- for (const node of remaining) {
82
- const cycle = dfs(node);
83
- if (cycle)
84
- return cycle;
85
- }
86
- return null;
87
- }
88
- /**
89
- * Sort graph in topological order with alphabetical sorting within layers
90
- * Returns enhanced format with level metadata
91
- *
92
- * @param graph - Unsorted dependency graph { project: [deps] }
93
- * @returns Sorted graph with level metadata { project: { level: number, dependsOn: [deps] } }
94
- */
95
- function sortGraphTopologically(graph) {
96
- const layers = computeTopologicalLayers(graph);
97
- const result = {};
98
- // Add projects layer by layer (dependencies before dependents)
99
- layers.forEach((layer, levelIndex) => {
100
- for (const project of layer) {
101
- // Already sorted alphabetically within layer
102
- result[project] = {
103
- level: levelIndex,
104
- dependsOn: (graph[project] || []).sort(),
105
- };
106
- }
107
- });
108
- return result;
109
- }
110
- //# sourceMappingURL=graph-sorter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"graph-sorter.js","sourceRoot":"","sources":["../../../../../../packages/tooling/dev-config/architecture/lib/graph-sorter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Graph Sorter\n *\n * Performs topological sorting on the dependency graph to:\n * 1. Detect circular dependencies (fails if cycle found)\n * 2. Assign level numbers to each project (level 0 = no deps, level 1 = depends on level 0, etc.)\n * 3. Group projects into layers for deterministic ordering\n */\n\n/**\n * Graph entry with level metadata\n */\nexport interface GraphEntry {\n level: number;\n dependsOn: string[];\n}\n\n/**\n * Enhanced graph format with level information\n */\nexport type EnhancedGraph = Record<string, GraphEntry>;\n\n/**\n * Compute topological layers for dependency graph using Kahn's algorithm\n *\n * Projects are grouped into layers where each layer only depends on previous layers.\n * Throws an error if a circular dependency is detected.\n *\n * @param graph - Dependency graph { project: [deps] }\n * @returns Array of layers, each containing sorted project names\n */\nexport function computeTopologicalLayers(graph: Record<string, string[]>): string[][] {\n const layers: string[][] = [];\n const processed = new Set<string>();\n const allProjects = Object.keys(graph);\n\n while (processed.size < allProjects.length) {\n const currentLayer: string[] = [];\n\n for (const project of allProjects) {\n if (processed.has(project)) continue;\n\n const deps = graph[project] || [];\n // Check if all dependencies are in previous layers (already processed)\n const allDepsInPrevLayers = deps.every((dep) => processed.has(dep));\n\n if (allDepsInPrevLayers) {\n currentLayer.push(project);\n }\n }\n\n if (currentLayer.length === 0) {\n // No progress made = circular dependency detected\n const remaining = allProjects.filter((p) => !processed.has(p));\n\n // Try to identify the cycle\n const cycleInfo = findCycle(graph, remaining);\n\n throw new Error(\n `Circular dependency detected among: ${remaining.join(', ')}\\n` +\n (cycleInfo ? `Cycle: ${cycleInfo}\\n` : '') +\n 'Fix: Remove one of the dependencies to break the cycle.'\n );\n }\n\n // Sort alphabetically within layer for deterministic output\n currentLayer.sort();\n layers.push(currentLayer);\n\n // Mark as processed\n currentLayer.forEach((p) => processed.add(p));\n }\n\n return layers;\n}\n\n/**\n * Try to find and describe a cycle in the graph\n */\nfunction findCycle(graph: Record<string, string[]>, remaining: string[]): string | null {\n const visited = new Set<string>();\n const path: string[] = [];\n\n function dfs(node: string): string | null {\n if (path.includes(node)) {\n const cycleStart = path.indexOf(node);\n return [...path.slice(cycleStart), node].join(' -> ');\n }\n if (visited.has(node)) return null;\n\n visited.add(node);\n path.push(node);\n\n const deps = graph[node] || [];\n for (const dep of deps) {\n if (remaining.includes(dep)) {\n const result = dfs(dep);\n if (result) return result;\n }\n }\n\n path.pop();\n return null;\n }\n\n for (const node of remaining) {\n const cycle = dfs(node);\n if (cycle) return cycle;\n }\n\n return null;\n}\n\n/**\n * Sort graph in topological order with alphabetical sorting within layers\n * Returns enhanced format with level metadata\n *\n * @param graph - Unsorted dependency graph { project: [deps] }\n * @returns Sorted graph with level metadata { project: { level: number, dependsOn: [deps] } }\n */\nexport function sortGraphTopologically(graph: Record<string, string[]>): EnhancedGraph {\n const layers = computeTopologicalLayers(graph);\n const result: EnhancedGraph = {};\n\n // Add projects layer by layer (dependencies before dependents)\n layers.forEach((layer, levelIndex) => {\n for (const project of layer) {\n // Already sorted alphabetically within layer\n result[project] = {\n level: levelIndex,\n dependsOn: (graph[project] || []).sort(),\n };\n }\n });\n\n return result;\n}\n"]}
@@ -1,137 +0,0 @@
1
- /**
2
- * Graph Sorter
3
- *
4
- * Performs topological sorting on the dependency graph to:
5
- * 1. Detect circular dependencies (fails if cycle found)
6
- * 2. Assign level numbers to each project (level 0 = no deps, level 1 = depends on level 0, etc.)
7
- * 3. Group projects into layers for deterministic ordering
8
- */
9
-
10
- /**
11
- * Graph entry with level metadata
12
- */
13
- export interface GraphEntry {
14
- level: number;
15
- dependsOn: string[];
16
- }
17
-
18
- /**
19
- * Enhanced graph format with level information
20
- */
21
- export type EnhancedGraph = Record<string, GraphEntry>;
22
-
23
- /**
24
- * Compute topological layers for dependency graph using Kahn's algorithm
25
- *
26
- * Projects are grouped into layers where each layer only depends on previous layers.
27
- * Throws an error if a circular dependency is detected.
28
- *
29
- * @param graph - Dependency graph { project: [deps] }
30
- * @returns Array of layers, each containing sorted project names
31
- */
32
- export function computeTopologicalLayers(graph: Record<string, string[]>): string[][] {
33
- const layers: string[][] = [];
34
- const processed = new Set<string>();
35
- const allProjects = Object.keys(graph);
36
-
37
- while (processed.size < allProjects.length) {
38
- const currentLayer: string[] = [];
39
-
40
- for (const project of allProjects) {
41
- if (processed.has(project)) continue;
42
-
43
- const deps = graph[project] || [];
44
- // Check if all dependencies are in previous layers (already processed)
45
- const allDepsInPrevLayers = deps.every((dep) => processed.has(dep));
46
-
47
- if (allDepsInPrevLayers) {
48
- currentLayer.push(project);
49
- }
50
- }
51
-
52
- if (currentLayer.length === 0) {
53
- // No progress made = circular dependency detected
54
- const remaining = allProjects.filter((p) => !processed.has(p));
55
-
56
- // Try to identify the cycle
57
- const cycleInfo = findCycle(graph, remaining);
58
-
59
- throw new Error(
60
- `Circular dependency detected among: ${remaining.join(', ')}\n` +
61
- (cycleInfo ? `Cycle: ${cycleInfo}\n` : '') +
62
- 'Fix: Remove one of the dependencies to break the cycle.'
63
- );
64
- }
65
-
66
- // Sort alphabetically within layer for deterministic output
67
- currentLayer.sort();
68
- layers.push(currentLayer);
69
-
70
- // Mark as processed
71
- currentLayer.forEach((p) => processed.add(p));
72
- }
73
-
74
- return layers;
75
- }
76
-
77
- /**
78
- * Try to find and describe a cycle in the graph
79
- */
80
- function findCycle(graph: Record<string, string[]>, remaining: string[]): string | null {
81
- const visited = new Set<string>();
82
- const path: string[] = [];
83
-
84
- function dfs(node: string): string | null {
85
- if (path.includes(node)) {
86
- const cycleStart = path.indexOf(node);
87
- return [...path.slice(cycleStart), node].join(' -> ');
88
- }
89
- if (visited.has(node)) return null;
90
-
91
- visited.add(node);
92
- path.push(node);
93
-
94
- const deps = graph[node] || [];
95
- for (const dep of deps) {
96
- if (remaining.includes(dep)) {
97
- const result = dfs(dep);
98
- if (result) return result;
99
- }
100
- }
101
-
102
- path.pop();
103
- return null;
104
- }
105
-
106
- for (const node of remaining) {
107
- const cycle = dfs(node);
108
- if (cycle) return cycle;
109
- }
110
-
111
- return null;
112
- }
113
-
114
- /**
115
- * Sort graph in topological order with alphabetical sorting within layers
116
- * Returns enhanced format with level metadata
117
- *
118
- * @param graph - Unsorted dependency graph { project: [deps] }
119
- * @returns Sorted graph with level metadata { project: { level: number, dependsOn: [deps] } }
120
- */
121
- export function sortGraphTopologically(graph: Record<string, string[]>): EnhancedGraph {
122
- const layers = computeTopologicalLayers(graph);
123
- const result: EnhancedGraph = {};
124
-
125
- // Add projects layer by layer (dependencies before dependents)
126
- layers.forEach((layer, levelIndex) => {
127
- for (const project of layer) {
128
- // Already sorted alphabetically within layer
129
- result[project] = {
130
- level: levelIndex,
131
- dependsOn: (graph[project] || []).sort(),
132
- };
133
- }
134
- });
135
-
136
- return result;
137
- }
@@ -1,29 +0,0 @@
1
- /**
2
- * Graph Visualizer
3
- *
4
- * Generates visual representations of the architecture graph:
5
- * - DOT format (for Graphviz)
6
- * - Interactive HTML (using viz.js)
7
- *
8
- * Output files go to tmp/webpieces/ for easy viewing without committing.
9
- */
10
- import type { EnhancedGraph } from './graph-sorter';
11
- /**
12
- * Generate Graphviz DOT format from the graph
13
- */
14
- export declare function generateDot(graph: EnhancedGraph, title?: string): string;
15
- /**
16
- * Generate interactive HTML with embedded SVG using viz.js
17
- */
18
- export declare function generateHTML(dot: string, title?: string): string;
19
- /**
20
- * Write visualization files to tmp/webpieces/
21
- */
22
- export declare function writeVisualization(graph: EnhancedGraph, workspaceRoot: string, title?: string): {
23
- dotPath: string;
24
- htmlPath: string;
25
- };
26
- /**
27
- * Open the HTML visualization in the default browser
28
- */
29
- export declare function openVisualization(htmlPath: string): boolean;