@webpieces/dev-config 0.2.95 → 0.2.98

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 (181) 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/src/executors/validate-eslint-sync/executor.js.map +1 -0
  7. package/{executors → src/executors}/validate-versions-locked/executor.js +2 -1
  8. package/src/executors/validate-versions-locked/executor.js.map +1 -0
  9. package/src/index.d.ts +1 -1
  10. package/src/index.js +1 -1
  11. package/src/index.js.map +1 -1
  12. package/src/plugin.d.ts +86 -0
  13. package/{plugin.js → src/plugin.js} +31 -15
  14. package/src/plugin.js.map +1 -0
  15. package/src/toError.d.ts +5 -0
  16. package/src/toError.js +37 -0
  17. package/src/toError.js.map +1 -0
  18. package/templates/eslint.webpieces.config.mjs +1 -1
  19. package/architecture/executors/diff-utils.d.ts +0 -24
  20. package/architecture/executors/diff-utils.js +0 -119
  21. package/architecture/executors/diff-utils.js.map +0 -1
  22. package/architecture/executors/diff-utils.ts +0 -127
  23. package/architecture/executors/generate/executor.d.ts +0 -16
  24. package/architecture/executors/generate/executor.js +0 -44
  25. package/architecture/executors/generate/executor.js.map +0 -1
  26. package/architecture/executors/generate/executor.ts +0 -59
  27. package/architecture/executors/generate/schema.json +0 -14
  28. package/architecture/executors/validate-architecture-unchanged/executor.d.ts +0 -17
  29. package/architecture/executors/validate-architecture-unchanged/executor.js +0 -229
  30. package/architecture/executors/validate-architecture-unchanged/executor.js.map +0 -1
  31. package/architecture/executors/validate-architecture-unchanged/executor.ts +0 -251
  32. package/architecture/executors/validate-architecture-unchanged/schema.json +0 -14
  33. package/architecture/executors/validate-code/executor.d.ts +0 -78
  34. package/architecture/executors/validate-code/executor.js +0 -243
  35. package/architecture/executors/validate-code/executor.js.map +0 -1
  36. package/architecture/executors/validate-code/executor.ts +0 -406
  37. package/architecture/executors/validate-code/schema.json +0 -227
  38. package/architecture/executors/validate-dtos/executor.d.ts +0 -42
  39. package/architecture/executors/validate-dtos/executor.js +0 -561
  40. package/architecture/executors/validate-dtos/executor.js.map +0 -1
  41. package/architecture/executors/validate-dtos/executor.ts +0 -689
  42. package/architecture/executors/validate-dtos/schema.json +0 -33
  43. package/architecture/executors/validate-modified-files/executor.d.ts +0 -25
  44. package/architecture/executors/validate-modified-files/executor.js +0 -501
  45. package/architecture/executors/validate-modified-files/executor.js.map +0 -1
  46. package/architecture/executors/validate-modified-files/executor.ts +0 -571
  47. package/architecture/executors/validate-modified-files/schema.json +0 -25
  48. package/architecture/executors/validate-modified-methods/executor.d.ts +0 -31
  49. package/architecture/executors/validate-modified-methods/executor.js +0 -694
  50. package/architecture/executors/validate-modified-methods/executor.js.map +0 -1
  51. package/architecture/executors/validate-modified-methods/executor.ts +0 -797
  52. package/architecture/executors/validate-modified-methods/schema.json +0 -25
  53. package/architecture/executors/validate-new-methods/executor.d.ts +0 -28
  54. package/architecture/executors/validate-new-methods/executor.js +0 -513
  55. package/architecture/executors/validate-new-methods/executor.js.map +0 -1
  56. package/architecture/executors/validate-new-methods/executor.ts +0 -584
  57. package/architecture/executors/validate-new-methods/schema.json +0 -25
  58. package/architecture/executors/validate-no-any-unknown/executor.d.ts +0 -42
  59. package/architecture/executors/validate-no-any-unknown/executor.js +0 -462
  60. package/architecture/executors/validate-no-any-unknown/executor.js.map +0 -1
  61. package/architecture/executors/validate-no-any-unknown/executor.ts +0 -540
  62. package/architecture/executors/validate-no-any-unknown/schema.json +0 -24
  63. package/architecture/executors/validate-no-architecture-cycles/executor.d.ts +0 -16
  64. package/architecture/executors/validate-no-architecture-cycles/executor.js +0 -48
  65. package/architecture/executors/validate-no-architecture-cycles/executor.js.map +0 -1
  66. package/architecture/executors/validate-no-architecture-cycles/executor.ts +0 -60
  67. package/architecture/executors/validate-no-architecture-cycles/schema.json +0 -8
  68. package/architecture/executors/validate-no-destructure/executor.d.ts +0 -52
  69. package/architecture/executors/validate-no-destructure/executor.js +0 -491
  70. package/architecture/executors/validate-no-destructure/executor.js.map +0 -1
  71. package/architecture/executors/validate-no-destructure/executor.ts +0 -578
  72. package/architecture/executors/validate-no-destructure/schema.json +0 -24
  73. package/architecture/executors/validate-no-direct-api-resolver/executor.d.ts +0 -47
  74. package/architecture/executors/validate-no-direct-api-resolver/executor.js +0 -566
  75. package/architecture/executors/validate-no-direct-api-resolver/executor.js.map +0 -1
  76. package/architecture/executors/validate-no-direct-api-resolver/executor.ts +0 -666
  77. package/architecture/executors/validate-no-direct-api-resolver/schema.json +0 -29
  78. package/architecture/executors/validate-no-inline-types/executor.d.ts +0 -91
  79. package/architecture/executors/validate-no-inline-types/executor.js +0 -669
  80. package/architecture/executors/validate-no-inline-types/executor.js.map +0 -1
  81. package/architecture/executors/validate-no-inline-types/executor.ts +0 -775
  82. package/architecture/executors/validate-no-inline-types/schema.json +0 -24
  83. package/architecture/executors/validate-no-skiplevel-deps/executor.d.ts +0 -19
  84. package/architecture/executors/validate-no-skiplevel-deps/executor.js +0 -227
  85. package/architecture/executors/validate-no-skiplevel-deps/executor.js.map +0 -1
  86. package/architecture/executors/validate-no-skiplevel-deps/executor.ts +0 -267
  87. package/architecture/executors/validate-no-skiplevel-deps/schema.json +0 -8
  88. package/architecture/executors/validate-packagejson/executor.d.ts +0 -16
  89. package/architecture/executors/validate-packagejson/executor.js +0 -57
  90. package/architecture/executors/validate-packagejson/executor.js.map +0 -1
  91. package/architecture/executors/validate-packagejson/executor.ts +0 -74
  92. package/architecture/executors/validate-packagejson/schema.json +0 -8
  93. package/architecture/executors/validate-prisma-converters/executor.d.ts +0 -60
  94. package/architecture/executors/validate-prisma-converters/executor.js +0 -634
  95. package/architecture/executors/validate-prisma-converters/executor.js.map +0 -1
  96. package/architecture/executors/validate-prisma-converters/executor.ts +0 -822
  97. package/architecture/executors/validate-prisma-converters/schema.json +0 -38
  98. package/architecture/executors/validate-return-types/executor.d.ts +0 -29
  99. package/architecture/executors/validate-return-types/executor.js +0 -439
  100. package/architecture/executors/validate-return-types/executor.js.map +0 -1
  101. package/architecture/executors/validate-return-types/executor.ts +0 -524
  102. package/architecture/executors/validate-return-types/schema.json +0 -24
  103. package/architecture/executors/visualize/executor.d.ts +0 -17
  104. package/architecture/executors/visualize/executor.js +0 -49
  105. package/architecture/executors/visualize/executor.js.map +0 -1
  106. package/architecture/executors/visualize/executor.ts +0 -63
  107. package/architecture/executors/visualize/schema.json +0 -14
  108. package/architecture/index.d.ts +0 -19
  109. package/architecture/index.js +0 -23
  110. package/architecture/index.js.map +0 -1
  111. package/architecture/index.ts +0 -20
  112. package/architecture/lib/graph-comparator.d.ts +0 -39
  113. package/architecture/lib/graph-comparator.js +0 -100
  114. package/architecture/lib/graph-comparator.js.map +0 -1
  115. package/architecture/lib/graph-comparator.ts +0 -141
  116. package/architecture/lib/graph-generator.d.ts +0 -19
  117. package/architecture/lib/graph-generator.js +0 -84
  118. package/architecture/lib/graph-generator.js.map +0 -1
  119. package/architecture/lib/graph-generator.ts +0 -97
  120. package/architecture/lib/graph-loader.d.ts +0 -31
  121. package/architecture/lib/graph-loader.js +0 -98
  122. package/architecture/lib/graph-loader.js.map +0 -1
  123. package/architecture/lib/graph-loader.ts +0 -116
  124. package/architecture/lib/graph-sorter.d.ts +0 -37
  125. package/architecture/lib/graph-sorter.js +0 -110
  126. package/architecture/lib/graph-sorter.js.map +0 -1
  127. package/architecture/lib/graph-sorter.ts +0 -137
  128. package/architecture/lib/graph-visualizer.d.ts +0 -29
  129. package/architecture/lib/graph-visualizer.js +0 -217
  130. package/architecture/lib/graph-visualizer.js.map +0 -1
  131. package/architecture/lib/graph-visualizer.ts +0 -231
  132. package/architecture/lib/package-validator.d.ts +0 -38
  133. package/architecture/lib/package-validator.js +0 -126
  134. package/architecture/lib/package-validator.js.map +0 -1
  135. package/architecture/lib/package-validator.ts +0 -170
  136. package/eslint-plugin/__tests__/catch-error-pattern.test.ts +0 -374
  137. package/eslint-plugin/__tests__/max-file-lines.test.ts +0 -207
  138. package/eslint-plugin/__tests__/max-method-lines.test.ts +0 -258
  139. package/eslint-plugin/__tests__/no-unmanaged-exceptions.test.ts +0 -359
  140. package/eslint-plugin/index.d.ts +0 -23
  141. package/eslint-plugin/index.js +0 -30
  142. package/eslint-plugin/index.js.map +0 -1
  143. package/eslint-plugin/index.ts +0 -29
  144. package/eslint-plugin/rules/catch-error-pattern.d.ts +0 -11
  145. package/eslint-plugin/rules/catch-error-pattern.js +0 -143
  146. package/eslint-plugin/rules/catch-error-pattern.js.map +0 -1
  147. package/eslint-plugin/rules/catch-error-pattern.ts +0 -246
  148. package/eslint-plugin/rules/enforce-architecture.d.ts +0 -15
  149. package/eslint-plugin/rules/enforce-architecture.js +0 -476
  150. package/eslint-plugin/rules/enforce-architecture.js.map +0 -1
  151. package/eslint-plugin/rules/enforce-architecture.ts +0 -543
  152. package/eslint-plugin/rules/max-file-lines.d.ts +0 -12
  153. package/eslint-plugin/rules/max-file-lines.js +0 -257
  154. package/eslint-plugin/rules/max-file-lines.js.map +0 -1
  155. package/eslint-plugin/rules/max-file-lines.ts +0 -272
  156. package/eslint-plugin/rules/max-method-lines.d.ts +0 -12
  157. package/eslint-plugin/rules/max-method-lines.js +0 -240
  158. package/eslint-plugin/rules/max-method-lines.js.map +0 -1
  159. package/eslint-plugin/rules/max-method-lines.ts +0 -287
  160. package/eslint-plugin/rules/no-unmanaged-exceptions.d.ts +0 -22
  161. package/eslint-plugin/rules/no-unmanaged-exceptions.js +0 -160
  162. package/eslint-plugin/rules/no-unmanaged-exceptions.js.map +0 -1
  163. package/eslint-plugin/rules/no-unmanaged-exceptions.ts +0 -179
  164. package/executors/help/executor.js.map +0 -1
  165. package/executors/help/executor.ts +0 -61
  166. package/executors/validate-eslint-sync/executor.js.map +0 -1
  167. package/executors/validate-eslint-sync/executor.ts +0 -87
  168. package/executors/validate-versions-locked/executor.js.map +0 -1
  169. package/executors/validate-versions-locked/executor.ts +0 -368
  170. package/plugin/README.md +0 -243
  171. package/plugin/index.d.ts +0 -4
  172. package/plugin/index.js +0 -8
  173. package/plugin/index.js.map +0 -1
  174. package/plugin/index.ts +0 -4
  175. /package/{executors → src/executors}/help/executor.js +0 -0
  176. /package/{executors → src/executors}/help/schema.json +0 -0
  177. /package/{executors → src/executors}/validate-eslint-sync/executor.d.ts +0 -0
  178. /package/{executors → src/executors}/validate-eslint-sync/executor.js +0 -0
  179. /package/{executors → src/executors}/validate-eslint-sync/schema.json +0 -0
  180. /package/{executors → src/executors}/validate-versions-locked/executor.d.ts +0 -0
  181. /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
- }