@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,524 +0,0 @@
1
- /**
2
- * Validate Return Types Executor
3
- *
4
- * Validates that methods have explicit return type annotations for better code readability.
5
- * Instead of relying on TypeScript's type inference, explicit return types make code clearer:
6
- *
7
- * BAD: method() { return new MyClass(); }
8
- * GOOD: method(): MyClass { return new MyClass(); }
9
- * GOOD: async method(): Promise<MyType> { ... }
10
- *
11
- * Modes:
12
- * - OFF: Skip validation entirely
13
- * - NEW_METHODS: Only validate new methods (detected via git diff)
14
- * - NEW_AND_MODIFIED_METHODS: Validate new methods + methods with changes in their line range
15
- * - MODIFIED_FILES: Validate all methods in modified files
16
- *
17
- * Escape hatch: Add webpieces-disable require-return-type comment with justification
18
- */
19
-
20
- import type { ExecutorContext } from '@nx/devkit';
21
- import { execSync } from 'child_process';
22
- import * as fs from 'fs';
23
- import * as path from 'path';
24
- import * as ts from 'typescript';
25
-
26
- export type ReturnTypeMode = 'OFF' | 'NEW_METHODS' | 'NEW_AND_MODIFIED_METHODS' | 'MODIFIED_FILES';
27
-
28
- export interface ValidateReturnTypesOptions {
29
- mode?: ReturnTypeMode;
30
- disableAllowed?: boolean;
31
- ignoreModifiedUntilEpoch?: number;
32
- }
33
-
34
- export interface ExecutorResult {
35
- success: boolean;
36
- }
37
-
38
- interface MethodViolation {
39
- file: string;
40
- methodName: string;
41
- line: number;
42
- }
43
-
44
- /**
45
- * Get changed TypeScript files between base and head (or working tree if head not specified).
46
- */
47
- // webpieces-disable max-lines-new-methods -- Git command handling with untracked files requires multiple code paths
48
- function getChangedTypeScriptFiles(workspaceRoot: string, base: string, head?: string): string[] {
49
- try {
50
- const diffTarget = head ? `${base} ${head}` : base;
51
- const output = execSync(`git diff --name-only ${diffTarget} -- '*.ts' '*.tsx'`, {
52
- cwd: workspaceRoot,
53
- encoding: 'utf-8',
54
- });
55
- const changedFiles = output
56
- .trim()
57
- .split('\n')
58
- .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
59
-
60
- if (!head) {
61
- try {
62
- const untrackedOutput = execSync(`git ls-files --others --exclude-standard '*.ts' '*.tsx'`, {
63
- cwd: workspaceRoot,
64
- encoding: 'utf-8',
65
- });
66
- const untrackedFiles = untrackedOutput
67
- .trim()
68
- .split('\n')
69
- .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
70
- const allFiles = new Set([...changedFiles, ...untrackedFiles]);
71
- return Array.from(allFiles);
72
- } catch {
73
- return changedFiles;
74
- }
75
- }
76
-
77
- return changedFiles;
78
- } catch {
79
- return [];
80
- }
81
- }
82
-
83
- /**
84
- * Get the diff content for a specific file.
85
- */
86
- function getFileDiff(workspaceRoot: string, file: string, base: string, head?: string): string {
87
- try {
88
- const diffTarget = head ? `${base} ${head}` : base;
89
- const diff = execSync(`git diff ${diffTarget} -- "${file}"`, {
90
- cwd: workspaceRoot,
91
- encoding: 'utf-8',
92
- });
93
-
94
- if (!diff && !head) {
95
- const fullPath = path.join(workspaceRoot, file);
96
- if (fs.existsSync(fullPath)) {
97
- const isUntracked = execSync(`git ls-files --others --exclude-standard "${file}"`, {
98
- cwd: workspaceRoot,
99
- encoding: 'utf-8',
100
- }).trim();
101
-
102
- if (isUntracked) {
103
- const content = fs.readFileSync(fullPath, 'utf-8');
104
- const lines = content.split('\n');
105
- return lines.map((line) => `+${line}`).join('\n');
106
- }
107
- }
108
- }
109
-
110
- return diff;
111
- } catch {
112
- return '';
113
- }
114
- }
115
-
116
- /**
117
- * Parse diff to find newly added method signatures.
118
- */
119
- function findNewMethodSignaturesInDiff(diffContent: string): Set<string> {
120
- const newMethods = new Set<string>();
121
- const lines = diffContent.split('\n');
122
-
123
- const patterns = [
124
- /^\+\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(/,
125
- /^\+\s*(?:export\s+)?(?:const|let)\s+(\w+)\s*=\s*(?:async\s*)?\(/,
126
- /^\+\s*(?:export\s+)?(?:const|let)\s+(\w+)\s*=\s*(?:async\s+)?function/,
127
- /^\+\s*(?:(?:public|private|protected)\s+)?(?:static\s+)?(?:async\s+)?(\w+)\s*\(/,
128
- ];
129
-
130
- for (const line of lines) {
131
- if (line.startsWith('+') && !line.startsWith('+++')) {
132
- for (const pattern of patterns) {
133
- const match = line.match(pattern);
134
- if (match) {
135
- const methodName = match[1];
136
- if (methodName && !['if', 'for', 'while', 'switch', 'catch', 'constructor'].includes(methodName)) {
137
- newMethods.add(methodName);
138
- }
139
- break;
140
- }
141
- }
142
- }
143
- }
144
-
145
- return newMethods;
146
- }
147
-
148
- /**
149
- * Check if a line contains a webpieces-disable comment for return type.
150
- */
151
- function hasDisableComment(lines: string[], lineNumber: number): boolean {
152
- const startCheck = Math.max(0, lineNumber - 5);
153
- for (let i = lineNumber - 2; i >= startCheck; i--) {
154
- const line = lines[i]?.trim() ?? '';
155
- if (line.startsWith('function ') || line.startsWith('class ') || line.endsWith('}')) {
156
- break;
157
- }
158
- if (line.includes('webpieces-disable') && line.includes('require-return-type')) {
159
- return true;
160
- }
161
- }
162
- return false;
163
- }
164
-
165
- /**
166
- * Check if a method has an explicit return type annotation.
167
- */
168
- function hasExplicitReturnType(node: ts.MethodDeclaration | ts.FunctionDeclaration | ts.ArrowFunction): boolean {
169
- return node.type !== undefined;
170
- }
171
-
172
- interface MethodInfo {
173
- name: string;
174
- line: number;
175
- endLine: number;
176
- hasReturnType: boolean;
177
- hasDisableComment: boolean;
178
- }
179
-
180
- /**
181
- * Parse a TypeScript file and find methods with their return type status.
182
- */
183
- // webpieces-disable max-lines-new-methods -- AST traversal requires inline visitor function
184
- function findMethodsInFile(filePath: string, workspaceRoot: string): MethodInfo[] {
185
- const fullPath = path.join(workspaceRoot, filePath);
186
- if (!fs.existsSync(fullPath)) return [];
187
-
188
- const content = fs.readFileSync(fullPath, 'utf-8');
189
- const fileLines = content.split('\n');
190
- const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
191
-
192
- const methods: MethodInfo[] = [];
193
-
194
- // webpieces-disable max-lines-new-methods -- AST visitor pattern requires handling multiple node types
195
- function visit(node: ts.Node): void {
196
- let methodName: string | undefined;
197
- let startLine: number | undefined;
198
- let endLine: number | undefined;
199
- let hasReturnType = false;
200
-
201
- if (ts.isMethodDeclaration(node) && node.name) {
202
- methodName = node.name.getText(sourceFile);
203
- const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());
204
- const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());
205
- startLine = start.line + 1;
206
- endLine = end.line + 1;
207
- hasReturnType = hasExplicitReturnType(node);
208
- } else if (ts.isFunctionDeclaration(node) && node.name) {
209
- methodName = node.name.getText(sourceFile);
210
- const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());
211
- const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());
212
- startLine = start.line + 1;
213
- endLine = end.line + 1;
214
- hasReturnType = hasExplicitReturnType(node);
215
- } else if (ts.isArrowFunction(node)) {
216
- if (ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {
217
- methodName = node.parent.name.getText(sourceFile);
218
- const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());
219
- const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());
220
- startLine = start.line + 1;
221
- endLine = end.line + 1;
222
- hasReturnType = hasExplicitReturnType(node);
223
- }
224
- }
225
-
226
- if (methodName && startLine !== undefined && endLine !== undefined) {
227
- methods.push({
228
- name: methodName,
229
- line: startLine,
230
- endLine,
231
- hasReturnType,
232
- hasDisableComment: hasDisableComment(fileLines, startLine),
233
- });
234
- }
235
-
236
- ts.forEachChild(node, visit);
237
- }
238
-
239
- visit(sourceFile);
240
- return methods;
241
- }
242
-
243
- /**
244
- * Parse diff to extract changed line numbers (both additions and modifications).
245
- */
246
- function getChangedLineNumbers(diffContent: string): Set<number> {
247
- const changedLines = new Set<number>();
248
- const lines = diffContent.split('\n');
249
- let currentLine = 0;
250
-
251
- for (const line of lines) {
252
- const hunkMatch = line.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
253
- if (hunkMatch) {
254
- currentLine = parseInt(hunkMatch[1], 10);
255
- continue;
256
- }
257
-
258
- if (line.startsWith('+') && !line.startsWith('+++')) {
259
- changedLines.add(currentLine);
260
- currentLine++;
261
- } else if (line.startsWith('-') && !line.startsWith('---')) {
262
- // Deletions don't increment line number
263
- } else {
264
- currentLine++;
265
- }
266
- }
267
-
268
- return changedLines;
269
- }
270
-
271
- /**
272
- * Check if a method has any changed lines within its range.
273
- */
274
- function methodHasChanges(method: MethodInfo, changedLines: Set<number>): boolean {
275
- for (let line = method.line; line <= method.endLine; line++) {
276
- if (changedLines.has(line)) {
277
- return true;
278
- }
279
- }
280
- return false;
281
- }
282
-
283
- /**
284
- * Find NEW methods without explicit return types (NEW_METHODS mode).
285
- */
286
- // webpieces-disable max-lines-new-methods -- File iteration with diff parsing and method matching
287
- function findViolationsForNewMethods(
288
- workspaceRoot: string,
289
- changedFiles: string[],
290
- base: string,
291
- head: string | undefined,
292
- disableAllowed: boolean
293
- ): MethodViolation[] {
294
- const violations: MethodViolation[] = [];
295
-
296
- for (const file of changedFiles) {
297
- const diff = getFileDiff(workspaceRoot, file, base, head);
298
- const newMethodNames = findNewMethodSignaturesInDiff(diff);
299
-
300
- if (newMethodNames.size === 0) continue;
301
-
302
- const methods = findMethodsInFile(file, workspaceRoot);
303
-
304
- for (const method of methods) {
305
- if (!newMethodNames.has(method.name)) continue;
306
- if (method.hasReturnType) continue;
307
- if (disableAllowed && method.hasDisableComment) continue;
308
-
309
- violations.push({
310
- file,
311
- methodName: method.name,
312
- line: method.line,
313
- });
314
- }
315
- }
316
-
317
- return violations;
318
- }
319
-
320
- /**
321
- * Find NEW methods AND methods with changes (NEW_AND_MODIFIED_METHODS mode).
322
- */
323
- // webpieces-disable max-lines-new-methods -- Combines new method detection with change detection
324
- function findViolationsForModifiedAndNewMethods(
325
- workspaceRoot: string,
326
- changedFiles: string[],
327
- base: string,
328
- head: string | undefined,
329
- disableAllowed: boolean
330
- ): MethodViolation[] {
331
- const violations: MethodViolation[] = [];
332
-
333
- for (const file of changedFiles) {
334
- const diff = getFileDiff(workspaceRoot, file, base, head);
335
- const newMethodNames = findNewMethodSignaturesInDiff(diff);
336
- const changedLines = getChangedLineNumbers(diff);
337
-
338
- const methods = findMethodsInFile(file, workspaceRoot);
339
-
340
- for (const method of methods) {
341
- if (method.hasReturnType) continue;
342
- if (disableAllowed && method.hasDisableComment) continue;
343
-
344
- const isNewMethod = newMethodNames.has(method.name);
345
- const isModifiedMethod = methodHasChanges(method, changedLines);
346
-
347
- if (!isNewMethod && !isModifiedMethod) continue;
348
-
349
- violations.push({
350
- file,
351
- methodName: method.name,
352
- line: method.line,
353
- });
354
- }
355
- }
356
-
357
- return violations;
358
- }
359
-
360
- /**
361
- * Find all methods without explicit return types in modified files (MODIFIED_FILES mode).
362
- */
363
- function findViolationsForModifiedFiles(workspaceRoot: string, changedFiles: string[], disableAllowed: boolean): MethodViolation[] {
364
- const violations: MethodViolation[] = [];
365
-
366
- for (const file of changedFiles) {
367
- const methods = findMethodsInFile(file, workspaceRoot);
368
-
369
- for (const method of methods) {
370
- if (method.hasReturnType) continue;
371
- if (disableAllowed && method.hasDisableComment) continue;
372
-
373
- violations.push({
374
- file,
375
- methodName: method.name,
376
- line: method.line,
377
- });
378
- }
379
- }
380
-
381
- return violations;
382
- }
383
-
384
- /**
385
- * Auto-detect the base branch by finding the merge-base with origin/main.
386
- */
387
- function detectBase(workspaceRoot: string): string | null {
388
- try {
389
- const mergeBase = execSync('git merge-base HEAD origin/main', {
390
- cwd: workspaceRoot,
391
- encoding: 'utf-8',
392
- stdio: ['pipe', 'pipe', 'pipe'],
393
- }).trim();
394
-
395
- if (mergeBase) {
396
- return mergeBase;
397
- }
398
- } catch {
399
- try {
400
- const mergeBase = execSync('git merge-base HEAD main', {
401
- cwd: workspaceRoot,
402
- encoding: 'utf-8',
403
- stdio: ['pipe', 'pipe', 'pipe'],
404
- }).trim();
405
-
406
- if (mergeBase) {
407
- return mergeBase;
408
- }
409
- } catch {
410
- // Ignore
411
- }
412
- }
413
- return null;
414
- }
415
-
416
- /**
417
- * Report violations to console.
418
- */
419
- function reportViolations(violations: MethodViolation[], mode: ReturnTypeMode): void {
420
- console.error('');
421
- console.error('❌ Methods missing explicit return types!');
422
- console.error('');
423
- console.error('📚 Explicit return types improve code readability:');
424
- console.error('');
425
- console.error(' BAD: method() { return new MyClass(); }');
426
- console.error(' GOOD: method(): MyClass { return new MyClass(); }');
427
- console.error(' GOOD: async method(): Promise<MyType> { ... }');
428
- console.error('');
429
-
430
- for (const v of violations) {
431
- console.error(` ❌ ${v.file}:${v.line}`);
432
- console.error(` Method: ${v.methodName} - missing return type annotation`);
433
- }
434
- console.error('');
435
-
436
- console.error(' To fix: Add explicit return type after the parameter list');
437
- console.error('');
438
- console.error(' Escape hatch (use sparingly):');
439
- console.error(' // webpieces-disable require-return-type -- [your reason]');
440
- console.error('');
441
- console.error(` Current mode: ${mode}`);
442
- console.error('');
443
- }
444
-
445
- /**
446
- * Resolve mode considering ignoreModifiedUntilEpoch override.
447
- * When active, downgrades to OFF. When expired, logs a warning.
448
- */
449
- function resolveMode(normalMode: ReturnTypeMode, epoch: number | undefined): ReturnTypeMode {
450
- if (epoch === undefined || normalMode === 'OFF') {
451
- return normalMode;
452
- }
453
- const nowSeconds = Date.now() / 1000;
454
- if (nowSeconds < epoch) {
455
- const expiresDate = new Date(epoch * 1000).toISOString().split('T')[0];
456
- console.log(`\n⏭️ Skipping require-return-type validation (ignoreModifiedUntilEpoch active, expires: ${expiresDate})`);
457
- console.log('');
458
- return 'OFF';
459
- }
460
- return normalMode;
461
- }
462
-
463
- export default async function runExecutor(
464
- options: ValidateReturnTypesOptions,
465
- context: ExecutorContext
466
- ): Promise<ExecutorResult> {
467
- const workspaceRoot = context.root;
468
- const mode: ReturnTypeMode = resolveMode(options.mode ?? 'NEW_METHODS', options.ignoreModifiedUntilEpoch);
469
- const disableAllowed = options.disableAllowed ?? true;
470
-
471
- if (mode === 'OFF') {
472
- console.log('\n⏭️ Skipping return type validation (mode: OFF)');
473
- console.log('');
474
- return { success: true };
475
- }
476
-
477
- console.log('\n📏 Validating Return Types\n');
478
- console.log(` Mode: ${mode}`);
479
-
480
- let base = process.env['NX_BASE'];
481
- const head = process.env['NX_HEAD'];
482
-
483
- if (!base) {
484
- base = detectBase(workspaceRoot) ?? undefined;
485
-
486
- if (!base) {
487
- console.log('\n⏭️ Skipping return type validation (could not detect base branch)');
488
- console.log('');
489
- return { success: true };
490
- }
491
- }
492
-
493
- console.log(` Base: ${base}`);
494
- console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
495
- console.log('');
496
-
497
- const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
498
-
499
- if (changedFiles.length === 0) {
500
- console.log('✅ No TypeScript files changed');
501
- return { success: true };
502
- }
503
-
504
- console.log(`📂 Checking ${changedFiles.length} changed file(s)...`);
505
-
506
- let violations: MethodViolation[] = [];
507
-
508
- if (mode === 'NEW_METHODS') {
509
- violations = findViolationsForNewMethods(workspaceRoot, changedFiles, base, head, disableAllowed);
510
- } else if (mode === 'NEW_AND_MODIFIED_METHODS') {
511
- violations = findViolationsForModifiedAndNewMethods(workspaceRoot, changedFiles, base, head, disableAllowed);
512
- } else if (mode === 'MODIFIED_FILES') {
513
- violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed);
514
- }
515
-
516
- if (violations.length === 0) {
517
- console.log('✅ All methods have explicit return types');
518
- return { success: true };
519
- }
520
-
521
- reportViolations(violations, mode);
522
-
523
- return { success: false };
524
- }
@@ -1,24 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/schema",
3
- "title": "Validate Return Types Executor",
4
- "description": "Validates that methods have explicit return type annotations for better code readability.",
5
- "type": "object",
6
- "properties": {
7
- "mode": {
8
- "type": "string",
9
- "enum": ["OFF", "NEW_METHODS", "NEW_AND_MODIFIED_METHODS", "MODIFIED_FILES"],
10
- "description": "OFF: skip validation. NEW_METHODS: only new methods in diff. NEW_AND_MODIFIED_METHODS: new methods + methods with changes. MODIFIED_FILES: all methods in modified files.",
11
- "default": "NEW_METHODS"
12
- },
13
- "disableAllowed": {
14
- "type": "boolean",
15
- "description": "Whether disable comments work. When false, no escape hatch.",
16
- "default": true
17
- },
18
- "ignoreModifiedUntilEpoch": {
19
- "type": "number",
20
- "description": "Epoch seconds. Until this time, skip validation entirely. When expired, normal mode resumes. Omit when not needed."
21
- }
22
- },
23
- "required": []
24
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * Visualize Executor
3
- *
4
- * Generates visual representations of the architecture graph (DOT + HTML)
5
- * and opens the visualization in a browser.
6
- *
7
- * Usage:
8
- * nx run architecture:visualize
9
- */
10
- import type { ExecutorContext } from '@nx/devkit';
11
- export interface VisualizeExecutorOptions {
12
- graphPath?: string;
13
- }
14
- export interface ExecutorResult {
15
- success: boolean;
16
- }
17
- export default function runExecutor(options: VisualizeExecutorOptions, context: ExecutorContext): Promise<ExecutorResult>;
@@ -1,49 +0,0 @@
1
- "use strict";
2
- /**
3
- * Visualize Executor
4
- *
5
- * Generates visual representations of the architecture graph (DOT + HTML)
6
- * and opens the visualization in a browser.
7
- *
8
- * Usage:
9
- * nx run architecture:visualize
10
- */
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.default = runExecutor;
13
- const graph_loader_1 = require("../../lib/graph-loader");
14
- const graph_visualizer_1 = require("../../lib/graph-visualizer");
15
- async function runExecutor(options, context) {
16
- const { graphPath } = options;
17
- const workspaceRoot = context.root;
18
- console.log('\n🎨 Architecture Visualization\n');
19
- try {
20
- // Load the saved graph
21
- console.log('📂 Loading saved graph...');
22
- const graph = (0, graph_loader_1.loadBlessedGraph)(workspaceRoot, graphPath);
23
- if (!graph) {
24
- console.error('❌ No saved graph found at architecture/dependencies.json');
25
- console.error(' Run: nx run architecture:generate first');
26
- return { success: false };
27
- }
28
- // Generate visualization
29
- console.log('🎨 Generating visualization...');
30
- const { dotPath, htmlPath } = (0, graph_visualizer_1.writeVisualization)(graph, workspaceRoot);
31
- console.log(`✅ Generated: ${dotPath}`);
32
- console.log(`✅ Generated: ${htmlPath}`);
33
- // Try to open in browser
34
- console.log('\n🌐 Opening visualization in browser...');
35
- if ((0, graph_visualizer_1.openVisualization)(htmlPath)) {
36
- console.log('✅ Browser opened');
37
- }
38
- else {
39
- console.log(`⚠️ Could not auto-open. Open manually: ${htmlPath}`);
40
- }
41
- return { success: true };
42
- }
43
- catch (err) {
44
- const error = err instanceof Error ? err : new Error(String(err));
45
- console.error('❌ Visualization failed:', error.message);
46
- return { success: false };
47
- }
48
- }
49
- //# sourceMappingURL=executor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/dev-config/architecture/executors/visualize/executor.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;AAcH,8BAwCC;AAnDD,yDAA0D;AAC1D,iEAAmF;AAUpE,KAAK,UAAU,WAAW,CACrC,OAAiC,EACjC,OAAwB;IAExB,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC9B,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAEnC,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IAEjD,IAAI,CAAC;QACD,uBAAuB;QACvB,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,IAAA,+BAAgB,EAAC,aAAa,EAAE,SAAS,CAAC,CAAC;QAEzD,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAC1E,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAC5D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC9B,CAAC;QAED,yBAAyB;QACzB,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;QAC9C,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAA,qCAAkB,EAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,gBAAgB,OAAO,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,gBAAgB,QAAQ,EAAE,CAAC,CAAC;QAExC,yBAAyB;QACzB,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;QACxD,IAAI,IAAA,oCAAiB,EAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QACpC,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,GAAG,CAAC,2CAA2C,QAAQ,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,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,yBAAyB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACxD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;AACL,CAAC","sourcesContent":["/**\n * Visualize Executor\n *\n * Generates visual representations of the architecture graph (DOT + HTML)\n * and opens the visualization in a browser.\n *\n * Usage:\n * nx run architecture:visualize\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport { loadBlessedGraph } from '../../lib/graph-loader';\nimport { writeVisualization, openVisualization } from '../../lib/graph-visualizer';\n\nexport interface VisualizeExecutorOptions {\n graphPath?: string;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nexport default async function runExecutor(\n options: VisualizeExecutorOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const { graphPath } = options;\n const workspaceRoot = context.root;\n\n console.log('\\n🎨 Architecture Visualization\\n');\n\n try {\n // Load the saved graph\n console.log('📂 Loading saved graph...');\n const graph = loadBlessedGraph(workspaceRoot, graphPath);\n\n if (!graph) {\n console.error('❌ No saved graph found at architecture/dependencies.json');\n console.error(' Run: nx run architecture:generate first');\n return { success: false };\n }\n\n // Generate visualization\n console.log('🎨 Generating visualization...');\n const { dotPath, htmlPath } = writeVisualization(graph, workspaceRoot);\n console.log(`✅ Generated: ${dotPath}`);\n console.log(`✅ Generated: ${htmlPath}`);\n\n // Try to open in browser\n console.log('\\n🌐 Opening visualization in browser...');\n if (openVisualization(htmlPath)) {\n console.log('✅ Browser opened');\n } else {\n console.log(`⚠️ Could not auto-open. Open manually: ${htmlPath}`);\n }\n\n return { success: true };\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n console.error('❌ Visualization failed:', error.message);\n return { success: false };\n }\n}\n"]}
@@ -1,63 +0,0 @@
1
- /**
2
- * Visualize Executor
3
- *
4
- * Generates visual representations of the architecture graph (DOT + HTML)
5
- * and opens the visualization in a browser.
6
- *
7
- * Usage:
8
- * nx run architecture:visualize
9
- */
10
-
11
- import type { ExecutorContext } from '@nx/devkit';
12
- import { loadBlessedGraph } from '../../lib/graph-loader';
13
- import { writeVisualization, openVisualization } from '../../lib/graph-visualizer';
14
-
15
- export interface VisualizeExecutorOptions {
16
- graphPath?: string;
17
- }
18
-
19
- export interface ExecutorResult {
20
- success: boolean;
21
- }
22
-
23
- export default async function runExecutor(
24
- options: VisualizeExecutorOptions,
25
- context: ExecutorContext
26
- ): Promise<ExecutorResult> {
27
- const { graphPath } = options;
28
- const workspaceRoot = context.root;
29
-
30
- console.log('\n🎨 Architecture Visualization\n');
31
-
32
- try {
33
- // Load the saved graph
34
- console.log('📂 Loading saved graph...');
35
- const graph = loadBlessedGraph(workspaceRoot, graphPath);
36
-
37
- if (!graph) {
38
- console.error('❌ No saved graph found at architecture/dependencies.json');
39
- console.error(' Run: nx run architecture:generate first');
40
- return { success: false };
41
- }
42
-
43
- // Generate visualization
44
- console.log('🎨 Generating visualization...');
45
- const { dotPath, htmlPath } = writeVisualization(graph, workspaceRoot);
46
- console.log(`✅ Generated: ${dotPath}`);
47
- console.log(`✅ Generated: ${htmlPath}`);
48
-
49
- // Try to open in browser
50
- console.log('\n🌐 Opening visualization in browser...');
51
- if (openVisualization(htmlPath)) {
52
- console.log('✅ Browser opened');
53
- } else {
54
- console.log(`⚠️ Could not auto-open. Open manually: ${htmlPath}`);
55
- }
56
-
57
- return { success: true };
58
- } catch (err: unknown) {
59
- const error = err instanceof Error ? err : new Error(String(err));
60
- console.error('❌ Visualization failed:', error.message);
61
- return { success: false };
62
- }
63
- }