@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,217 +0,0 @@
1
- "use strict";
2
- /**
3
- * Graph Visualizer
4
- *
5
- * Generates visual representations of the architecture graph:
6
- * - DOT format (for Graphviz)
7
- * - Interactive HTML (using viz.js)
8
- *
9
- * Output files go to tmp/webpieces/ for easy viewing without committing.
10
- */
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.generateDot = generateDot;
13
- exports.generateHTML = generateHTML;
14
- exports.writeVisualization = writeVisualization;
15
- exports.openVisualization = openVisualization;
16
- const tslib_1 = require("tslib");
17
- const fs = tslib_1.__importStar(require("fs"));
18
- const path = tslib_1.__importStar(require("path"));
19
- const child_process_1 = require("child_process");
20
- /**
21
- * Level colors for visualization
22
- */
23
- const LEVEL_COLORS = {
24
- 0: '#E8F5E9', // Light green - foundation
25
- 1: '#E3F2FD', // Light blue - middleware
26
- 2: '#FFF3E0', // Light orange - applications
27
- 3: '#FCE4EC', // Light pink - higher level
28
- };
29
- /**
30
- * Remove scope from name for display
31
- * '@scope/name' → 'name'
32
- * 'name' → 'name'
33
- */
34
- function getShortName(name) {
35
- return name.includes('/') ? name.split('/').pop() : name;
36
- }
37
- /**
38
- * Generate Graphviz DOT format from the graph
39
- */
40
- function generateDot(graph, title = 'WebPieces Architecture') {
41
- let dot = 'digraph Architecture {\n';
42
- dot += ' rankdir=TB;\n';
43
- dot += ' node [shape=box, style=filled, fontname="Arial"];\n';
44
- dot += ' edge [fontname="Arial"];\n\n';
45
- // Group projects by level
46
- const levels = {};
47
- for (const [project, info] of Object.entries(graph)) {
48
- if (!levels[info.level])
49
- levels[info.level] = [];
50
- levels[info.level].push(project);
51
- }
52
- // Create nodes with level-based colors
53
- for (const [project, info] of Object.entries(graph)) {
54
- const shortName = getShortName(project);
55
- const color = LEVEL_COLORS[info.level] || '#F5F5F5';
56
- dot += ` "${shortName}" [fillcolor="${color}", label="${shortName}\\n(L${info.level})"];\n`;
57
- }
58
- dot += '\n';
59
- // Create same-rank subgraphs for each level
60
- for (const [level, projects] of Object.entries(levels)) {
61
- dot += ` { rank=same; `;
62
- projects.forEach((p) => {
63
- const shortName = getShortName(p);
64
- dot += `"${shortName}"; `;
65
- });
66
- dot += '}\n';
67
- }
68
- dot += '\n';
69
- // Create edges (dependencies)
70
- for (const [project, info] of Object.entries(graph)) {
71
- const shortName = getShortName(project);
72
- for (const dep of info.dependsOn || []) {
73
- const depShortName = getShortName(dep);
74
- dot += ` "${shortName}" -> "${depShortName}";\n`;
75
- }
76
- }
77
- dot += '\n labelloc="t";\n';
78
- dot += ` label="${title}\\n(from architecture/dependencies.json)";\n`;
79
- dot += ' fontsize=20;\n';
80
- dot += '}\n';
81
- return dot;
82
- }
83
- /**
84
- * Generate interactive HTML with embedded SVG using viz.js
85
- */
86
- function generateHTML(dot, title = 'WebPieces Architecture') {
87
- return `<!DOCTYPE html>
88
- <html>
89
- <head>
90
- <title>${title}</title>
91
- <script src="https://cdn.jsdelivr.net/npm/viz.js@2.1.2/viz.js"></script>
92
- <script src="https://cdn.jsdelivr.net/npm/viz.js@2.1.2/full.render.js"></script>
93
- <style>
94
- body {
95
- margin: 0;
96
- padding: 20px;
97
- font-family: Arial, sans-serif;
98
- background: #f5f5f5;
99
- }
100
- h1 {
101
- text-align: center;
102
- color: #333;
103
- }
104
- #graph {
105
- text-align: center;
106
- background: white;
107
- padding: 20px;
108
- border-radius: 8px;
109
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
110
- }
111
- .legend {
112
- margin: 20px auto;
113
- max-width: 600px;
114
- padding: 15px;
115
- background: white;
116
- border-radius: 8px;
117
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
118
- }
119
- .legend h2 {
120
- margin-top: 0;
121
- }
122
- .legend-item {
123
- margin: 8px 0;
124
- }
125
- .legend-box {
126
- display: inline-block;
127
- width: 20px;
128
- height: 20px;
129
- border: 1px solid #ccc;
130
- margin-right: 10px;
131
- vertical-align: middle;
132
- }
133
- </style>
134
- </head>
135
- <body>
136
- <h1>${title}</h1>
137
-
138
- <div class="legend">
139
- <h2>Legend</h2>
140
- <div class="legend-item">
141
- <span class="legend-box" style="background: #E8F5E9;"></span>
142
- <strong>Level 0:</strong> Foundation libraries (no dependencies)
143
- </div>
144
- <div class="legend-item">
145
- <span class="legend-box" style="background: #E3F2FD;"></span>
146
- <strong>Level 1:</strong> Middleware libraries (depend on Level 0)
147
- </div>
148
- <div class="legend-item">
149
- <span class="legend-box" style="background: #FFF3E0;"></span>
150
- <strong>Level 2:</strong> Applications (depend on Level 1)
151
- </div>
152
- <div class="legend-item" style="margin-top: 15px;">
153
- <em>Note: Transitive dependencies are allowed but not shown in the graph.</em>
154
- </div>
155
- </div>
156
-
157
- <div id="graph"></div>
158
-
159
- <script>
160
- const dot = ${JSON.stringify(dot)};
161
- const viz = new Viz();
162
-
163
- viz.renderSVGElement(dot)
164
- .then(element => {
165
- document.getElementById('graph').appendChild(element);
166
- })
167
- .catch(err => {
168
- console.error(err);
169
- document.getElementById('graph').innerHTML = '<pre>' + err + '</pre>';
170
- });
171
- </script>
172
- </body>
173
- </html>`;
174
- }
175
- /**
176
- * Write visualization files to tmp/webpieces/
177
- */
178
- function writeVisualization(graph, workspaceRoot, title = 'WebPieces Architecture') {
179
- const outputDir = path.join(workspaceRoot, 'tmp', 'webpieces');
180
- // Ensure directory exists
181
- if (!fs.existsSync(outputDir)) {
182
- fs.mkdirSync(outputDir, { recursive: true });
183
- }
184
- // Generate DOT
185
- const dot = generateDot(graph, title);
186
- const dotPath = path.join(outputDir, 'architecture.dot');
187
- fs.writeFileSync(dotPath, dot, 'utf-8');
188
- // Generate HTML
189
- const html = generateHTML(dot, title);
190
- const htmlPath = path.join(outputDir, 'architecture.html');
191
- fs.writeFileSync(htmlPath, html, 'utf-8');
192
- return { dotPath, htmlPath };
193
- }
194
- /**
195
- * Open the HTML visualization in the default browser
196
- */
197
- function openVisualization(htmlPath) {
198
- try {
199
- const platform = process.platform;
200
- let openCommand;
201
- if (platform === 'darwin') {
202
- openCommand = `open "${htmlPath}"`;
203
- }
204
- else if (platform === 'win32') {
205
- openCommand = `start "" "${htmlPath}"`;
206
- }
207
- else {
208
- openCommand = `xdg-open "${htmlPath}"`;
209
- }
210
- (0, child_process_1.execSync)(openCommand, { stdio: 'ignore' });
211
- return true;
212
- }
213
- catch (err) {
214
- return false;
215
- }
216
- }
217
- //# sourceMappingURL=graph-visualizer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"graph-visualizer.js","sourceRoot":"","sources":["../../../../../../packages/tooling/dev-config/architecture/lib/graph-visualizer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Graph Visualizer\n *\n * Generates visual representations of the architecture graph:\n * - DOT format (for Graphviz)\n * - Interactive HTML (using viz.js)\n *\n * Output files go to tmp/webpieces/ for easy viewing without committing.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { execSync } from 'child_process';\nimport type { EnhancedGraph } from './graph-sorter';\n\n/**\n * Level colors for visualization\n */\nconst LEVEL_COLORS: Record<number, string> = {\n 0: '#E8F5E9', // Light green - foundation\n 1: '#E3F2FD', // Light blue - middleware\n 2: '#FFF3E0', // Light orange - applications\n 3: '#FCE4EC', // Light pink - higher level\n};\n\n/**\n * Remove scope from name for display\n * '@scope/name' → 'name'\n * 'name' → 'name'\n */\nfunction getShortName(name: string): string {\n return name.includes('/') ? name.split('/').pop()! : name;\n}\n\n/**\n * Generate Graphviz DOT format from the graph\n */\nexport function generateDot(graph: EnhancedGraph, title: string = 'WebPieces Architecture'): string {\n let dot = 'digraph Architecture {\\n';\n dot += ' rankdir=TB;\\n';\n dot += ' node [shape=box, style=filled, fontname=\"Arial\"];\\n';\n dot += ' edge [fontname=\"Arial\"];\\n\\n';\n\n // Group projects by level\n const levels: Record<number, string[]> = {};\n for (const [project, info] of Object.entries(graph)) {\n if (!levels[info.level]) levels[info.level] = [];\n levels[info.level].push(project);\n }\n\n // Create nodes with level-based colors\n for (const [project, info] of Object.entries(graph)) {\n const shortName = getShortName(project);\n const color = LEVEL_COLORS[info.level] || '#F5F5F5';\n dot += ` \"${shortName}\" [fillcolor=\"${color}\", label=\"${shortName}\\\\n(L${info.level})\"];\\n`;\n }\n\n dot += '\\n';\n\n // Create same-rank subgraphs for each level\n for (const [level, projects] of Object.entries(levels)) {\n dot += ` { rank=same; `;\n projects.forEach((p) => {\n const shortName = getShortName(p);\n dot += `\"${shortName}\"; `;\n });\n dot += '}\\n';\n }\n\n dot += '\\n';\n\n // Create edges (dependencies)\n for (const [project, info] of Object.entries(graph)) {\n const shortName = getShortName(project);\n for (const dep of info.dependsOn || []) {\n const depShortName = getShortName(dep);\n dot += ` \"${shortName}\" -> \"${depShortName}\";\\n`;\n }\n }\n\n dot += '\\n labelloc=\"t\";\\n';\n dot += ` label=\"${title}\\\\n(from architecture/dependencies.json)\";\\n`;\n dot += ' fontsize=20;\\n';\n dot += '}\\n';\n\n return dot;\n}\n\n/**\n * Generate interactive HTML with embedded SVG using viz.js\n */\nexport function generateHTML(dot: string, title: string = 'WebPieces Architecture'): string {\n return `<!DOCTYPE html>\n<html>\n<head>\n <title>${title}</title>\n <script src=\"https://cdn.jsdelivr.net/npm/viz.js@2.1.2/viz.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/viz.js@2.1.2/full.render.js\"></script>\n <style>\n body {\n margin: 0;\n padding: 20px;\n font-family: Arial, sans-serif;\n background: #f5f5f5;\n }\n h1 {\n text-align: center;\n color: #333;\n }\n #graph {\n text-align: center;\n background: white;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n .legend {\n margin: 20px auto;\n max-width: 600px;\n padding: 15px;\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n .legend h2 {\n margin-top: 0;\n }\n .legend-item {\n margin: 8px 0;\n }\n .legend-box {\n display: inline-block;\n width: 20px;\n height: 20px;\n border: 1px solid #ccc;\n margin-right: 10px;\n vertical-align: middle;\n }\n </style>\n</head>\n<body>\n <h1>${title}</h1>\n\n <div class=\"legend\">\n <h2>Legend</h2>\n <div class=\"legend-item\">\n <span class=\"legend-box\" style=\"background: #E8F5E9;\"></span>\n <strong>Level 0:</strong> Foundation libraries (no dependencies)\n </div>\n <div class=\"legend-item\">\n <span class=\"legend-box\" style=\"background: #E3F2FD;\"></span>\n <strong>Level 1:</strong> Middleware libraries (depend on Level 0)\n </div>\n <div class=\"legend-item\">\n <span class=\"legend-box\" style=\"background: #FFF3E0;\"></span>\n <strong>Level 2:</strong> Applications (depend on Level 1)\n </div>\n <div class=\"legend-item\" style=\"margin-top: 15px;\">\n <em>Note: Transitive dependencies are allowed but not shown in the graph.</em>\n </div>\n </div>\n\n <div id=\"graph\"></div>\n\n <script>\n const dot = ${JSON.stringify(dot)};\n const viz = new Viz();\n\n viz.renderSVGElement(dot)\n .then(element => {\n document.getElementById('graph').appendChild(element);\n })\n .catch(err => {\n console.error(err);\n document.getElementById('graph').innerHTML = '<pre>' + err + '</pre>';\n });\n </script>\n</body>\n</html>`;\n}\n\n/**\n * Write visualization files to tmp/webpieces/\n */\nexport function writeVisualization(\n graph: EnhancedGraph,\n workspaceRoot: string,\n title: string = 'WebPieces Architecture'\n): { dotPath: string; htmlPath: string } {\n const outputDir = path.join(workspaceRoot, 'tmp', 'webpieces');\n\n // Ensure directory exists\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n // Generate DOT\n const dot = generateDot(graph, title);\n const dotPath = path.join(outputDir, 'architecture.dot');\n fs.writeFileSync(dotPath, dot, 'utf-8');\n\n // Generate HTML\n const html = generateHTML(dot, title);\n const htmlPath = path.join(outputDir, 'architecture.html');\n fs.writeFileSync(htmlPath, html, 'utf-8');\n\n return { dotPath, htmlPath };\n}\n\n/**\n * Open the HTML visualization in the default browser\n */\nexport function openVisualization(htmlPath: string): boolean {\n try {\n const platform = process.platform;\n let openCommand: string;\n\n if (platform === 'darwin') {\n openCommand = `open \"${htmlPath}\"`;\n } else if (platform === 'win32') {\n openCommand = `start \"\" \"${htmlPath}\"`;\n } else {\n openCommand = `xdg-open \"${htmlPath}\"`;\n }\n\n execSync(openCommand, { stdio: 'ignore' });\n return true;\n } catch (err: unknown) {\n return false;\n }\n}\n"]}
@@ -1,231 +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
-
11
- import * as fs from 'fs';
12
- import * as path from 'path';
13
- import { execSync } from 'child_process';
14
- import type { EnhancedGraph } from './graph-sorter';
15
-
16
- /**
17
- * Level colors for visualization
18
- */
19
- const LEVEL_COLORS: Record<number, string> = {
20
- 0: '#E8F5E9', // Light green - foundation
21
- 1: '#E3F2FD', // Light blue - middleware
22
- 2: '#FFF3E0', // Light orange - applications
23
- 3: '#FCE4EC', // Light pink - higher level
24
- };
25
-
26
- /**
27
- * Remove scope from name for display
28
- * '@scope/name' → 'name'
29
- * 'name' → 'name'
30
- */
31
- function getShortName(name: string): string {
32
- return name.includes('/') ? name.split('/').pop()! : name;
33
- }
34
-
35
- /**
36
- * Generate Graphviz DOT format from the graph
37
- */
38
- export function generateDot(graph: EnhancedGraph, title: string = 'WebPieces Architecture'): string {
39
- let dot = 'digraph Architecture {\n';
40
- dot += ' rankdir=TB;\n';
41
- dot += ' node [shape=box, style=filled, fontname="Arial"];\n';
42
- dot += ' edge [fontname="Arial"];\n\n';
43
-
44
- // Group projects by level
45
- const levels: Record<number, string[]> = {};
46
- for (const [project, info] of Object.entries(graph)) {
47
- if (!levels[info.level]) levels[info.level] = [];
48
- levels[info.level].push(project);
49
- }
50
-
51
- // Create nodes with level-based colors
52
- for (const [project, info] of Object.entries(graph)) {
53
- const shortName = getShortName(project);
54
- const color = LEVEL_COLORS[info.level] || '#F5F5F5';
55
- dot += ` "${shortName}" [fillcolor="${color}", label="${shortName}\\n(L${info.level})"];\n`;
56
- }
57
-
58
- dot += '\n';
59
-
60
- // Create same-rank subgraphs for each level
61
- for (const [level, projects] of Object.entries(levels)) {
62
- dot += ` { rank=same; `;
63
- projects.forEach((p) => {
64
- const shortName = getShortName(p);
65
- dot += `"${shortName}"; `;
66
- });
67
- dot += '}\n';
68
- }
69
-
70
- dot += '\n';
71
-
72
- // Create edges (dependencies)
73
- for (const [project, info] of Object.entries(graph)) {
74
- const shortName = getShortName(project);
75
- for (const dep of info.dependsOn || []) {
76
- const depShortName = getShortName(dep);
77
- dot += ` "${shortName}" -> "${depShortName}";\n`;
78
- }
79
- }
80
-
81
- dot += '\n labelloc="t";\n';
82
- dot += ` label="${title}\\n(from architecture/dependencies.json)";\n`;
83
- dot += ' fontsize=20;\n';
84
- dot += '}\n';
85
-
86
- return dot;
87
- }
88
-
89
- /**
90
- * Generate interactive HTML with embedded SVG using viz.js
91
- */
92
- export function generateHTML(dot: string, title: string = 'WebPieces Architecture'): string {
93
- return `<!DOCTYPE html>
94
- <html>
95
- <head>
96
- <title>${title}</title>
97
- <script src="https://cdn.jsdelivr.net/npm/viz.js@2.1.2/viz.js"></script>
98
- <script src="https://cdn.jsdelivr.net/npm/viz.js@2.1.2/full.render.js"></script>
99
- <style>
100
- body {
101
- margin: 0;
102
- padding: 20px;
103
- font-family: Arial, sans-serif;
104
- background: #f5f5f5;
105
- }
106
- h1 {
107
- text-align: center;
108
- color: #333;
109
- }
110
- #graph {
111
- text-align: center;
112
- background: white;
113
- padding: 20px;
114
- border-radius: 8px;
115
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
116
- }
117
- .legend {
118
- margin: 20px auto;
119
- max-width: 600px;
120
- padding: 15px;
121
- background: white;
122
- border-radius: 8px;
123
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
124
- }
125
- .legend h2 {
126
- margin-top: 0;
127
- }
128
- .legend-item {
129
- margin: 8px 0;
130
- }
131
- .legend-box {
132
- display: inline-block;
133
- width: 20px;
134
- height: 20px;
135
- border: 1px solid #ccc;
136
- margin-right: 10px;
137
- vertical-align: middle;
138
- }
139
- </style>
140
- </head>
141
- <body>
142
- <h1>${title}</h1>
143
-
144
- <div class="legend">
145
- <h2>Legend</h2>
146
- <div class="legend-item">
147
- <span class="legend-box" style="background: #E8F5E9;"></span>
148
- <strong>Level 0:</strong> Foundation libraries (no dependencies)
149
- </div>
150
- <div class="legend-item">
151
- <span class="legend-box" style="background: #E3F2FD;"></span>
152
- <strong>Level 1:</strong> Middleware libraries (depend on Level 0)
153
- </div>
154
- <div class="legend-item">
155
- <span class="legend-box" style="background: #FFF3E0;"></span>
156
- <strong>Level 2:</strong> Applications (depend on Level 1)
157
- </div>
158
- <div class="legend-item" style="margin-top: 15px;">
159
- <em>Note: Transitive dependencies are allowed but not shown in the graph.</em>
160
- </div>
161
- </div>
162
-
163
- <div id="graph"></div>
164
-
165
- <script>
166
- const dot = ${JSON.stringify(dot)};
167
- const viz = new Viz();
168
-
169
- viz.renderSVGElement(dot)
170
- .then(element => {
171
- document.getElementById('graph').appendChild(element);
172
- })
173
- .catch(err => {
174
- console.error(err);
175
- document.getElementById('graph').innerHTML = '<pre>' + err + '</pre>';
176
- });
177
- </script>
178
- </body>
179
- </html>`;
180
- }
181
-
182
- /**
183
- * Write visualization files to tmp/webpieces/
184
- */
185
- export function writeVisualization(
186
- graph: EnhancedGraph,
187
- workspaceRoot: string,
188
- title: string = 'WebPieces Architecture'
189
- ): { dotPath: string; htmlPath: string } {
190
- const outputDir = path.join(workspaceRoot, 'tmp', 'webpieces');
191
-
192
- // Ensure directory exists
193
- if (!fs.existsSync(outputDir)) {
194
- fs.mkdirSync(outputDir, { recursive: true });
195
- }
196
-
197
- // Generate DOT
198
- const dot = generateDot(graph, title);
199
- const dotPath = path.join(outputDir, 'architecture.dot');
200
- fs.writeFileSync(dotPath, dot, 'utf-8');
201
-
202
- // Generate HTML
203
- const html = generateHTML(dot, title);
204
- const htmlPath = path.join(outputDir, 'architecture.html');
205
- fs.writeFileSync(htmlPath, html, 'utf-8');
206
-
207
- return { dotPath, htmlPath };
208
- }
209
-
210
- /**
211
- * Open the HTML visualization in the default browser
212
- */
213
- export function openVisualization(htmlPath: string): boolean {
214
- try {
215
- const platform = process.platform;
216
- let openCommand: string;
217
-
218
- if (platform === 'darwin') {
219
- openCommand = `open "${htmlPath}"`;
220
- } else if (platform === 'win32') {
221
- openCommand = `start "" "${htmlPath}"`;
222
- } else {
223
- openCommand = `xdg-open "${htmlPath}"`;
224
- }
225
-
226
- execSync(openCommand, { stdio: 'ignore' });
227
- return true;
228
- } catch (err: unknown) {
229
- return false;
230
- }
231
- }
@@ -1,38 +0,0 @@
1
- /**
2
- * Package Validator
3
- *
4
- * Validates that package.json dependencies match the project.json build.dependsOn
5
- * This ensures the two sources of truth don't drift apart.
6
- */
7
- /**
8
- * Validation result for a single project
9
- */
10
- export interface ProjectValidationResult {
11
- project: string;
12
- valid: boolean;
13
- missingInPackageJson: string[];
14
- extraInPackageJson: string[];
15
- }
16
- /**
17
- * Overall validation result
18
- */
19
- export interface ValidationResult {
20
- valid: boolean;
21
- errors: string[];
22
- projectResults: ProjectValidationResult[];
23
- }
24
- /**
25
- * Validate that package.json dependencies match the dependency graph
26
- *
27
- * For each project in the graph:
28
- * - Check that all graph dependencies exist in package.json
29
- * - Maps project names to package names for accurate comparison
30
- *
31
- * @param graph - Enhanced graph with project dependencies (uses project names)
32
- * @param workspaceRoot - Absolute path to workspace root
33
- * @returns Validation result with errors if any
34
- */
35
- export declare function validatePackageJsonDependencies(graph: Record<string, {
36
- level: number;
37
- dependsOn: string[];
38
- }>, workspaceRoot: string): Promise<ValidationResult>;
@@ -1,126 +0,0 @@
1
- "use strict";
2
- /**
3
- * Package Validator
4
- *
5
- * Validates that package.json dependencies match the project.json build.dependsOn
6
- * This ensures the two sources of truth don't drift apart.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.validatePackageJsonDependencies = validatePackageJsonDependencies;
10
- const tslib_1 = require("tslib");
11
- const fs = tslib_1.__importStar(require("fs"));
12
- const path = tslib_1.__importStar(require("path"));
13
- const devkit_1 = require("@nx/devkit");
14
- /**
15
- * Read package.json dependencies for a project
16
- * Returns null if package.json doesn't exist (apps often don't have one)
17
- */
18
- function readPackageJsonDeps(workspaceRoot, projectRoot) {
19
- const packageJsonPath = path.join(workspaceRoot, projectRoot, 'package.json');
20
- if (!fs.existsSync(packageJsonPath)) {
21
- return null; // No package.json - skip validation for this project
22
- }
23
- try {
24
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
25
- const deps = [];
26
- // Collect ALL dependencies from package.json
27
- for (const depType of ['dependencies', 'peerDependencies']) {
28
- const depObj = packageJson[depType] || {};
29
- for (const depName of Object.keys(depObj)) {
30
- if (!deps.includes(depName)) {
31
- deps.push(depName);
32
- }
33
- }
34
- }
35
- return deps.sort();
36
- }
37
- catch (err) {
38
- console.warn(`Could not read package.json at ${packageJsonPath}`);
39
- return [];
40
- }
41
- }
42
- /**
43
- * Build map of project names to their package names
44
- * e.g., "core-util" → "@webpieces/core-util"
45
- */
46
- function buildProjectToPackageMap(workspaceRoot, projectsConfig) {
47
- const map = new Map();
48
- for (const [projectName, config] of Object.entries(projectsConfig.projects)) {
49
- const packageJsonPath = path.join(workspaceRoot, config.root, 'package.json');
50
- if (fs.existsSync(packageJsonPath)) {
51
- try {
52
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
53
- if (packageJson.name) {
54
- map.set(projectName, packageJson.name);
55
- }
56
- }
57
- catch {
58
- // Ignore parse errors
59
- }
60
- }
61
- }
62
- return map;
63
- }
64
- /**
65
- * Validate that package.json dependencies match the dependency graph
66
- *
67
- * For each project in the graph:
68
- * - Check that all graph dependencies exist in package.json
69
- * - Maps project names to package names for accurate comparison
70
- *
71
- * @param graph - Enhanced graph with project dependencies (uses project names)
72
- * @param workspaceRoot - Absolute path to workspace root
73
- * @returns Validation result with errors if any
74
- */
75
- async function validatePackageJsonDependencies(graph, workspaceRoot) {
76
- const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
77
- const projectsConfig = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
78
- // Build map: project name → package name
79
- const projectToPackage = buildProjectToPackageMap(workspaceRoot, projectsConfig);
80
- const errors = [];
81
- const projectResults = [];
82
- for (const [projectName, entry] of Object.entries(graph)) {
83
- // Find the project config using project name directly
84
- const projectConfig = projectsConfig.projects[projectName];
85
- if (!projectConfig) {
86
- continue;
87
- }
88
- const projectRoot = projectConfig.root;
89
- const packageJsonDeps = readPackageJsonDeps(workspaceRoot, projectRoot);
90
- if (packageJsonDeps === null) {
91
- continue;
92
- }
93
- // Convert graph dependencies (project names) to package names for comparison
94
- const missingInPackageJson = [];
95
- for (const depProjectName of entry.dependsOn) {
96
- const depPackageName = projectToPackage.get(depProjectName) || depProjectName;
97
- if (!packageJsonDeps.includes(depPackageName)) {
98
- missingInPackageJson.push(depProjectName);
99
- }
100
- }
101
- // Check for extra dependencies in package.json (not critical, just informational)
102
- const extraInPackageJson = [];
103
- for (const dep of packageJsonDeps) {
104
- if (!entry.dependsOn.includes(dep)) {
105
- extraInPackageJson.push(dep);
106
- }
107
- }
108
- const valid = missingInPackageJson.length === 0;
109
- if (!valid) {
110
- errors.push(`Project ${projectName} (${projectRoot}/package.json) is missing dependencies: ${missingInPackageJson.join(', ')}\n` +
111
- ` Fix: Add these to package.json dependencies`);
112
- }
113
- projectResults.push({
114
- project: projectName,
115
- valid,
116
- missingInPackageJson,
117
- extraInPackageJson,
118
- });
119
- }
120
- return {
121
- valid: errors.length === 0,
122
- errors,
123
- projectResults,
124
- };
125
- }
126
- //# sourceMappingURL=package-validator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"package-validator.js","sourceRoot":"","sources":["../../../../../../packages/tooling/dev-config/architecture/lib/package-validator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Package Validator\n *\n * Validates that package.json dependencies match the project.json build.dependsOn\n * This ensures the two sources of truth don't drift apart.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport {\n createProjectGraphAsync,\n readProjectsConfigurationFromProjectGraph,\n} from '@nx/devkit';\n\n/**\n * Validation result for a single project\n */\nexport interface ProjectValidationResult {\n project: string;\n valid: boolean;\n missingInPackageJson: string[];\n extraInPackageJson: string[];\n}\n\n/**\n * Overall validation result\n */\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n projectResults: ProjectValidationResult[];\n}\n\n/**\n * Read package.json dependencies for a project\n * Returns null if package.json doesn't exist (apps often don't have one)\n */\nfunction readPackageJsonDeps(workspaceRoot: string, projectRoot: string): string[] | null {\n const packageJsonPath = path.join(workspaceRoot, projectRoot, 'package.json');\n\n if (!fs.existsSync(packageJsonPath)) {\n return null; // No package.json - skip validation for this project\n }\n\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n const deps: string[] = [];\n\n // Collect ALL dependencies from package.json\n for (const depType of ['dependencies', 'peerDependencies']) {\n const depObj = packageJson[depType] || {};\n for (const depName of Object.keys(depObj)) {\n if (!deps.includes(depName)) {\n deps.push(depName);\n }\n }\n }\n\n return deps.sort();\n } catch (err: unknown) {\n console.warn(`Could not read package.json at ${packageJsonPath}`);\n return [];\n }\n}\n\n/**\n * Build map of project names to their package names\n * e.g., \"core-util\" → \"@webpieces/core-util\"\n */\nfunction buildProjectToPackageMap(\n workspaceRoot: string,\n projectsConfig: any\n): Map<string, string> {\n const map = new Map<string, string>();\n\n for (const [projectName, config] of Object.entries<any>(projectsConfig.projects)) {\n const packageJsonPath = path.join(workspaceRoot, config.root, 'package.json');\n if (fs.existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n if (packageJson.name) {\n map.set(projectName, packageJson.name);\n }\n } catch {\n // Ignore parse errors\n }\n }\n }\n\n return map;\n}\n\n/**\n * Validate that package.json dependencies match the dependency graph\n *\n * For each project in the graph:\n * - Check that all graph dependencies exist in package.json\n * - Maps project names to package names for accurate comparison\n *\n * @param graph - Enhanced graph with project dependencies (uses project names)\n * @param workspaceRoot - Absolute path to workspace root\n * @returns Validation result with errors if any\n */\nexport async function validatePackageJsonDependencies(\n graph: Record<string, { level: number; dependsOn: string[] }>,\n workspaceRoot: string\n): Promise<ValidationResult> {\n const projectGraph = await createProjectGraphAsync();\n const projectsConfig = readProjectsConfigurationFromProjectGraph(projectGraph);\n\n // Build map: project name → package name\n const projectToPackage = buildProjectToPackageMap(workspaceRoot, projectsConfig);\n\n const errors: string[] = [];\n const projectResults: ProjectValidationResult[] = [];\n\n for (const [projectName, entry] of Object.entries(graph)) {\n // Find the project config using project name directly\n const projectConfig = projectsConfig.projects[projectName];\n if (!projectConfig) {\n continue;\n }\n\n const projectRoot = projectConfig.root;\n const packageJsonDeps = readPackageJsonDeps(workspaceRoot, projectRoot);\n\n if (packageJsonDeps === null) {\n continue;\n }\n\n // Convert graph dependencies (project names) to package names for comparison\n const missingInPackageJson: string[] = [];\n for (const depProjectName of entry.dependsOn) {\n const depPackageName = projectToPackage.get(depProjectName) || depProjectName;\n if (!packageJsonDeps.includes(depPackageName)) {\n missingInPackageJson.push(depProjectName);\n }\n }\n\n // Check for extra dependencies in package.json (not critical, just informational)\n const extraInPackageJson: string[] = [];\n for (const dep of packageJsonDeps) {\n if (!entry.dependsOn.includes(dep)) {\n extraInPackageJson.push(dep);\n }\n }\n\n const valid = missingInPackageJson.length === 0;\n\n if (!valid) {\n errors.push(\n `Project ${projectName} (${projectRoot}/package.json) is missing dependencies: ${missingInPackageJson.join(', ')}\\n` +\n ` Fix: Add these to package.json dependencies`\n );\n }\n\n projectResults.push({\n project: projectName,\n valid,\n missingInPackageJson,\n extraInPackageJson,\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n projectResults,\n };\n}\n"]}