@webpieces/dev-config 0.2.75 → 0.2.77

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 (37) hide show
  1. package/architecture/executors/validate-code/executor.d.ts +14 -6
  2. package/architecture/executors/validate-code/executor.js +61 -37
  3. package/architecture/executors/validate-code/executor.js.map +1 -1
  4. package/architecture/executors/validate-code/executor.ts +94 -58
  5. package/architecture/executors/validate-code/schema.json +48 -29
  6. package/architecture/executors/validate-modified-files/executor.d.ts +4 -3
  7. package/architecture/executors/validate-modified-files/executor.js +32 -30
  8. package/architecture/executors/validate-modified-files/executor.js.map +1 -1
  9. package/architecture/executors/validate-modified-files/executor.ts +36 -33
  10. package/architecture/executors/validate-modified-files/schema.json +9 -4
  11. package/architecture/executors/validate-modified-methods/executor.d.ts +7 -6
  12. package/architecture/executors/validate-modified-methods/executor.js +53 -47
  13. package/architecture/executors/validate-modified-methods/executor.js.map +1 -1
  14. package/architecture/executors/validate-modified-methods/executor.ts +57 -51
  15. package/architecture/executors/validate-modified-methods/schema.json +10 -5
  16. package/architecture/executors/validate-new-methods/executor.d.ts +4 -4
  17. package/architecture/executors/validate-new-methods/executor.js +64 -83
  18. package/architecture/executors/validate-new-methods/executor.js.map +1 -1
  19. package/architecture/executors/validate-new-methods/executor.ts +75 -96
  20. package/architecture/executors/validate-new-methods/schema.json +11 -10
  21. package/architecture/executors/validate-no-any-unknown/executor.d.ts +1 -2
  22. package/architecture/executors/validate-no-any-unknown/executor.js +57 -55
  23. package/architecture/executors/validate-no-any-unknown/executor.js.map +1 -1
  24. package/architecture/executors/validate-no-any-unknown/executor.ts +62 -57
  25. package/architecture/executors/validate-no-any-unknown/schema.json +2 -2
  26. package/architecture/executors/validate-no-inline-types/executor.d.ts +1 -2
  27. package/architecture/executors/validate-no-inline-types/executor.js +25 -58
  28. package/architecture/executors/validate-no-inline-types/executor.js.map +1 -1
  29. package/architecture/executors/validate-no-inline-types/executor.ts +26 -59
  30. package/architecture/executors/validate-no-inline-types/schema.json +2 -2
  31. package/architecture/executors/validate-return-types/executor.d.ts +1 -2
  32. package/architecture/executors/validate-return-types/executor.js +25 -58
  33. package/architecture/executors/validate-return-types/executor.js.map +1 -1
  34. package/architecture/executors/validate-return-types/executor.ts +26 -59
  35. package/architecture/executors/validate-return-types/schema.json +2 -2
  36. package/package.json +1 -1
  37. package/plugin.js +24 -7
@@ -22,7 +22,6 @@
22
22
  * - OFF: Skip validation entirely
23
23
  * - MODIFIED_CODE: Flag any/unknown on changed lines (lines in diff hunks)
24
24
  * - MODIFIED_FILES: Flag ALL any/unknown in files that were modified
25
- * - ALL: Flag everywhere in all TypeScript files
26
25
  *
27
26
  * ============================================================================
28
27
  * ESCAPE HATCH
@@ -76,24 +75,6 @@ function getChangedTypeScriptFiles(workspaceRoot, base, head) {
76
75
  return [];
77
76
  }
78
77
  }
79
- /**
80
- * Get all TypeScript files in the workspace using git ls-files (excluding tests).
81
- */
82
- function getAllTypeScriptFiles(workspaceRoot) {
83
- try {
84
- const output = (0, child_process_1.execSync)(`git ls-files '*.ts' '*.tsx'`, {
85
- cwd: workspaceRoot,
86
- encoding: 'utf-8',
87
- });
88
- return output
89
- .trim()
90
- .split('\n')
91
- .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
92
- }
93
- catch {
94
- return [];
95
- }
96
- }
97
78
  /**
98
79
  * Get the diff content for a specific file.
99
80
  */
@@ -212,6 +193,31 @@ function getViolationContext(node, sourceFile) {
212
193
  return 'type position';
213
194
  }
214
195
  }
196
+ /**
197
+ * Check if a node is in a catch clause variable declaration.
198
+ * This allows `catch (err: any)` and `catch (err: unknown)` patterns.
199
+ */
200
+ function isInCatchClause(node) {
201
+ let current = node.parent;
202
+ while (current) {
203
+ if (ts.isCatchClause(current)) {
204
+ // We're somewhere in a catch clause - check if we're in the variable declaration
205
+ const catchClause = current;
206
+ if (catchClause.variableDeclaration) {
207
+ // Walk back up from the original node to see if we're part of the variable declaration
208
+ let checkNode = node.parent;
209
+ while (checkNode && checkNode !== current) {
210
+ if (checkNode === catchClause.variableDeclaration) {
211
+ return true;
212
+ }
213
+ checkNode = checkNode.parent;
214
+ }
215
+ }
216
+ }
217
+ current = current.parent;
218
+ }
219
+ return false;
220
+ }
215
221
  /**
216
222
  * Find all `any` and `unknown` keywords in a file using AST.
217
223
  */
@@ -229,6 +235,11 @@ function findAnyUnknownInFile(filePath, workspaceRoot) {
229
235
  try {
230
236
  // Detect `any` keyword
231
237
  if (node.kind === ts.SyntaxKind.AnyKeyword) {
238
+ // Skip catch clause variable types: catch (err: any) is allowed
239
+ if (isInCatchClause(node)) {
240
+ ts.forEachChild(node, visit);
241
+ return;
242
+ }
232
243
  const startPos = node.getStart(sourceFile);
233
244
  if (startPos >= 0) {
234
245
  const pos = sourceFile.getLineAndCharacterOfPosition(startPos);
@@ -247,6 +258,11 @@ function findAnyUnknownInFile(filePath, workspaceRoot) {
247
258
  }
248
259
  // Detect `unknown` keyword
249
260
  if (node.kind === ts.SyntaxKind.UnknownKeyword) {
261
+ // Skip catch clause variable types: catch (err: unknown) is allowed
262
+ if (isInCatchClause(node)) {
263
+ ts.forEachChild(node, visit);
264
+ return;
265
+ }
250
266
  const startPos = node.getStart(sourceFile);
251
267
  if (startPos >= 0) {
252
268
  const pos = sourceFile.getLineAndCharacterOfPosition(startPos);
@@ -323,13 +339,6 @@ function findViolationsForModifiedFiles(workspaceRoot, changedFiles) {
323
339
  }
324
340
  return violations;
325
341
  }
326
- /**
327
- * ALL mode: Flag violations in all TypeScript files.
328
- */
329
- function findViolationsForAll(workspaceRoot) {
330
- const allFiles = getAllTypeScriptFiles(workspaceRoot);
331
- return findViolationsForModifiedFiles(workspaceRoot, allFiles);
332
- }
333
342
  /**
334
343
  * Auto-detect the base branch by finding the merge-base with origin/main.
335
344
  */
@@ -399,38 +408,31 @@ async function runExecutor(options, context) {
399
408
  }
400
409
  console.log('\nšŸ“ Validating No Any/Unknown\n');
401
410
  console.log(` Mode: ${mode}`);
402
- let violations = [];
403
- if (mode === 'ALL') {
404
- console.log(' Scope: All tracked TypeScript files');
405
- console.log('');
406
- violations = findViolationsForAll(workspaceRoot);
407
- }
408
- else {
409
- let base = process.env['NX_BASE'];
410
- const head = process.env['NX_HEAD'];
411
+ let base = process.env['NX_BASE'];
412
+ const head = process.env['NX_HEAD'];
413
+ if (!base) {
414
+ base = detectBase(workspaceRoot) ?? undefined;
411
415
  if (!base) {
412
- base = detectBase(workspaceRoot) ?? undefined;
413
- if (!base) {
414
- console.log('\nā­ļø Skipping no-any-unknown validation (could not detect base branch)');
415
- console.log('');
416
- return { success: true };
417
- }
418
- }
419
- console.log(` Base: ${base}`);
420
- console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
421
- console.log('');
422
- const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
423
- if (changedFiles.length === 0) {
424
- console.log('āœ… No TypeScript files changed');
416
+ console.log('\nā­ļø Skipping no-any-unknown validation (could not detect base branch)');
417
+ console.log('');
425
418
  return { success: true };
426
419
  }
427
- console.log(`šŸ“‚ Checking ${changedFiles.length} changed file(s)...`);
428
- if (mode === 'MODIFIED_CODE') {
429
- violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head);
430
- }
431
- else if (mode === 'MODIFIED_FILES') {
432
- violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles);
433
- }
420
+ }
421
+ console.log(` Base: ${base}`);
422
+ console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
423
+ console.log('');
424
+ const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
425
+ if (changedFiles.length === 0) {
426
+ console.log('āœ… No TypeScript files changed');
427
+ return { success: true };
428
+ }
429
+ console.log(`šŸ“‚ Checking ${changedFiles.length} changed file(s)...`);
430
+ let violations = [];
431
+ if (mode === 'MODIFIED_CODE') {
432
+ violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head);
433
+ }
434
+ else if (mode === 'MODIFIED_FILES') {
435
+ violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles);
434
436
  }
435
437
  if (violations.length === 0) {
436
438
  console.log('āœ… No any/unknown keywords found');
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/dev-config/architecture/executors/validate-no-any-unknown/executor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate No Any Unknown Executor\n *\n * Validates that `any` and `unknown` TypeScript keywords are not used.\n * Uses LINE-BASED detection (not method-based) for git diff filtering.\n *\n * ============================================================================\n * VIOLATIONS (BAD) - These patterns are flagged:\n * ============================================================================\n *\n * - const x: any = ...\n * - function foo(arg: any): any { }\n * - const data = response as any;\n * - type T = any;\n * - const x: unknown = ...\n * - function foo(arg: unknown): unknown { }\n *\n * ============================================================================\n * MODES (LINE-BASED)\n * ============================================================================\n * - OFF: Skip validation entirely\n * - MODIFIED_CODE: Flag any/unknown on changed lines (lines in diff hunks)\n * - MODIFIED_FILES: Flag ALL any/unknown in files that were modified\n * - ALL: Flag everywhere in all TypeScript files\n *\n * ============================================================================\n * ESCAPE HATCH\n * ============================================================================\n * Add comment above the violation:\n * // webpieces-disable no-any-unknown -- [your justification]\n * const x: any = ...;\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport { execSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as ts from 'typescript';\n\nexport type NoAnyUnknownMode = 'OFF' | 'MODIFIED_CODE' | 'MODIFIED_FILES' | 'ALL';\n\nexport interface ValidateNoAnyUnknownOptions {\n mode?: NoAnyUnknownMode;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\ninterface AnyUnknownViolation {\n file: string;\n line: number;\n column: number;\n keyword: 'any' | 'unknown';\n context: string;\n}\n\n/**\n * Get changed TypeScript files between base and head (or working tree if head not specified).\n */\n// webpieces-disable max-lines-new-methods -- Git command handling with untracked files requires multiple code paths\nfunction getChangedTypeScriptFiles(workspaceRoot: string, base: string, head?: string): string[] {\n try {\n const diffTarget = head ? `${base} ${head}` : base;\n const output = execSync(`git diff --name-only ${diffTarget} -- '*.ts' '*.tsx'`, {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n });\n const changedFiles = output\n .trim()\n .split('\\n')\n .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));\n\n if (!head) {\n try {\n const untrackedOutput = execSync(`git ls-files --others --exclude-standard '*.ts' '*.tsx'`, {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n });\n const untrackedFiles = untrackedOutput\n .trim()\n .split('\\n')\n .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));\n const allFiles = new Set([...changedFiles, ...untrackedFiles]);\n return Array.from(allFiles);\n } catch {\n return changedFiles;\n }\n }\n\n return changedFiles;\n } catch {\n return [];\n }\n}\n\n/**\n * Get all TypeScript files in the workspace using git ls-files (excluding tests).\n */\nfunction getAllTypeScriptFiles(workspaceRoot: string): string[] {\n try {\n const output = execSync(`git ls-files '*.ts' '*.tsx'`, {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n });\n return output\n .trim()\n .split('\\n')\n .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));\n } catch {\n return [];\n }\n}\n\n/**\n * Get the diff content for a specific file.\n */\nfunction getFileDiff(workspaceRoot: string, file: string, base: string, head?: string): string {\n try {\n const diffTarget = head ? `${base} ${head}` : base;\n const diff = execSync(`git diff ${diffTarget} -- \"${file}\"`, {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n });\n\n if (!diff && !head) {\n const fullPath = path.join(workspaceRoot, file);\n if (fs.existsSync(fullPath)) {\n const isUntracked = execSync(`git ls-files --others --exclude-standard \"${file}\"`, {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n }).trim();\n\n if (isUntracked) {\n const content = fs.readFileSync(fullPath, 'utf-8');\n const lines = content.split('\\n');\n return lines.map((line) => `+${line}`).join('\\n');\n }\n }\n }\n\n return diff;\n } catch {\n return '';\n }\n}\n\n/**\n * Parse diff to extract changed line numbers (additions only - lines starting with +).\n */\nfunction getChangedLineNumbers(diffContent: string): Set<number> {\n const changedLines = new Set<number>();\n const lines = diffContent.split('\\n');\n let currentLine = 0;\n\n for (const line of lines) {\n const hunkMatch = line.match(/^@@ -\\d+(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@/);\n if (hunkMatch) {\n currentLine = parseInt(hunkMatch[1], 10);\n continue;\n }\n\n if (line.startsWith('+') && !line.startsWith('+++')) {\n changedLines.add(currentLine);\n currentLine++;\n } else if (line.startsWith('-') && !line.startsWith('---')) {\n // Deletions don't increment line number\n } else {\n currentLine++;\n }\n }\n\n return changedLines;\n}\n\n/**\n * Check if a line contains a webpieces-disable comment for no-any-unknown.\n */\nfunction hasDisableComment(lines: string[], lineNumber: number): boolean {\n const startCheck = Math.max(0, lineNumber - 5);\n for (let i = lineNumber - 2; i >= startCheck; i--) {\n const line = lines[i]?.trim() ?? '';\n if (line.startsWith('function ') || line.startsWith('class ') || line.endsWith('}')) {\n break;\n }\n if (line.includes('webpieces-disable') && line.includes('no-any-unknown')) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Get a description of the context where the any/unknown keyword appears.\n */\n// webpieces-disable max-lines-new-methods -- Context detection requires checking many AST node types\nfunction getViolationContext(node: ts.Node, sourceFile: ts.SourceFile): string {\n try {\n let current: ts.Node = node;\n while (current.parent) {\n const parent = current.parent;\n if (ts.isParameter(parent)) {\n return 'parameter type';\n }\n if (ts.isFunctionDeclaration(parent) || ts.isMethodDeclaration(parent) || ts.isArrowFunction(parent)) {\n if (parent.type === current) {\n return 'return type';\n }\n }\n if (ts.isVariableDeclaration(parent)) {\n return 'variable type';\n }\n if (ts.isPropertyDeclaration(parent) || ts.isPropertySignature(parent)) {\n return 'property type';\n }\n if (ts.isAsExpression(parent)) {\n return 'type assertion';\n }\n if (ts.isTypeAliasDeclaration(parent)) {\n return 'type alias';\n }\n if (ts.isTypeReferenceNode(parent)) {\n return 'generic argument';\n }\n if (ts.isArrayTypeNode(parent)) {\n return 'array element type';\n }\n if (ts.isUnionTypeNode(parent) || ts.isIntersectionTypeNode(parent)) {\n return 'union/intersection type';\n }\n current = parent;\n }\n return 'type position';\n } catch {\n return 'type position';\n }\n}\n\ninterface AnyUnknownInfo {\n line: number;\n column: number;\n keyword: 'any' | 'unknown';\n context: string;\n hasDisableComment: boolean;\n}\n\n/**\n * Find all `any` and `unknown` keywords in a file using AST.\n */\n// webpieces-disable max-lines-new-methods -- AST traversal with nested visitor function for keyword detection\nfunction findAnyUnknownInFile(filePath: string, workspaceRoot: string): AnyUnknownInfo[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const fileLines = content.split('\\n');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n const violations: AnyUnknownInfo[] = [];\n\n // webpieces-disable max-lines-new-methods -- AST visitor needs to handle both any and unknown keywords with full context detection\n function visit(node: ts.Node): void {\n try {\n // Detect `any` keyword\n if (node.kind === ts.SyntaxKind.AnyKeyword) {\n const startPos = node.getStart(sourceFile);\n if (startPos >= 0) {\n const pos = sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n const column = pos.character + 1;\n const context = getViolationContext(node, sourceFile);\n const disabled = hasDisableComment(fileLines, line);\n\n violations.push({\n line,\n column,\n keyword: 'any',\n context,\n hasDisableComment: disabled,\n });\n }\n }\n\n // Detect `unknown` keyword\n if (node.kind === ts.SyntaxKind.UnknownKeyword) {\n const startPos = node.getStart(sourceFile);\n if (startPos >= 0) {\n const pos = sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n const column = pos.character + 1;\n const context = getViolationContext(node, sourceFile);\n const disabled = hasDisableComment(fileLines, line);\n\n violations.push({\n line,\n column,\n keyword: 'unknown',\n context,\n hasDisableComment: disabled,\n });\n }\n }\n } catch {\n // Skip nodes that cause errors during analysis\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return violations;\n}\n\n/**\n * MODIFIED_CODE mode: Flag violations on changed lines in diff hunks.\n * This is LINE-BASED detection.\n */\n// webpieces-disable max-lines-new-methods -- File iteration with diff parsing and line filtering\nfunction findViolationsForModifiedCode(\n workspaceRoot: string,\n changedFiles: string[],\n base: string,\n head?: string\n): AnyUnknownViolation[] {\n const violations: AnyUnknownViolation[] = [];\n\n for (const file of changedFiles) {\n const diff = getFileDiff(workspaceRoot, file, base, head);\n const changedLines = getChangedLineNumbers(diff);\n\n if (changedLines.size === 0) continue;\n\n const allViolations = findAnyUnknownInFile(file, workspaceRoot);\n\n for (const v of allViolations) {\n if (v.hasDisableComment) continue;\n // LINE-BASED: Only include if the violation is on a changed line\n if (!changedLines.has(v.line)) continue;\n\n violations.push({\n file,\n line: v.line,\n column: v.column,\n keyword: v.keyword,\n context: v.context,\n });\n }\n }\n\n return violations;\n}\n\n/**\n * MODIFIED_FILES mode: Flag ALL violations in files that were modified.\n */\nfunction findViolationsForModifiedFiles(workspaceRoot: string, changedFiles: string[]): AnyUnknownViolation[] {\n const violations: AnyUnknownViolation[] = [];\n\n for (const file of changedFiles) {\n const allViolations = findAnyUnknownInFile(file, workspaceRoot);\n\n for (const v of allViolations) {\n if (v.hasDisableComment) continue;\n\n violations.push({\n file,\n line: v.line,\n column: v.column,\n keyword: v.keyword,\n context: v.context,\n });\n }\n }\n\n return violations;\n}\n\n/**\n * ALL mode: Flag violations in all TypeScript files.\n */\nfunction findViolationsForAll(workspaceRoot: string): AnyUnknownViolation[] {\n const allFiles = getAllTypeScriptFiles(workspaceRoot);\n return findViolationsForModifiedFiles(workspaceRoot, allFiles);\n}\n\n/**\n * Auto-detect the base branch by finding the merge-base with origin/main.\n */\nfunction detectBase(workspaceRoot: string): string | null {\n try {\n const mergeBase = execSync('git merge-base HEAD origin/main', {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n\n if (mergeBase) {\n return mergeBase;\n }\n } catch {\n try {\n const mergeBase = execSync('git merge-base HEAD main', {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n\n if (mergeBase) {\n return mergeBase;\n }\n } catch {\n // Ignore\n }\n }\n return null;\n}\n\n/**\n * Report violations to console.\n */\nfunction reportViolations(violations: AnyUnknownViolation[], mode: NoAnyUnknownMode): void {\n console.error('');\n console.error('āŒ `any` and `unknown` keywords found! Use specific types instead.');\n console.error('');\n console.error('šŸ“š Avoiding any/unknown improves type safety:');\n console.error('');\n console.error(' BAD: const data: any = fetchData();');\n console.error(' GOOD: const data: UserData = fetchData();');\n console.error('');\n console.error(' BAD: function process(input: unknown): unknown { }');\n console.error(' GOOD: function process(input: ValidInput): ValidOutput { }');\n console.error('');\n\n for (const v of violations) {\n console.error(` āŒ ${v.file}:${v.line}:${v.column}`);\n console.error(` \\`${v.keyword}\\` keyword in ${v.context}`);\n }\n console.error('');\n\n console.error(' To fix: Replace with specific types or interfaces');\n console.error('');\n console.error(' Escape hatch (use sparingly):');\n console.error(' // webpieces-disable no-any-unknown -- [your reason]');\n console.error('');\n console.error(` Current mode: ${mode}`);\n console.error('');\n}\n\nexport default async function runExecutor(\n options: ValidateNoAnyUnknownOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const workspaceRoot = context.root;\n const mode: NoAnyUnknownMode = options.mode ?? 'OFF';\n\n if (mode === 'OFF') {\n console.log('\\nā­ļø Skipping no-any-unknown validation (mode: OFF)');\n console.log('');\n return { success: true };\n }\n\n console.log('\\nšŸ“ Validating No Any/Unknown\\n');\n console.log(` Mode: ${mode}`);\n\n let violations: AnyUnknownViolation[] = [];\n\n if (mode === 'ALL') {\n console.log(' Scope: All tracked TypeScript files');\n console.log('');\n violations = findViolationsForAll(workspaceRoot);\n } else {\n let base = process.env['NX_BASE'];\n const head = process.env['NX_HEAD'];\n\n if (!base) {\n base = detectBase(workspaceRoot) ?? undefined;\n\n if (!base) {\n console.log('\\nā­ļø Skipping no-any-unknown validation (could not detect base branch)');\n console.log('');\n return { success: true };\n }\n }\n\n console.log(` Base: ${base}`);\n console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);\n console.log('');\n\n const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);\n\n if (changedFiles.length === 0) {\n console.log('āœ… No TypeScript files changed');\n return { success: true };\n }\n\n console.log(`šŸ“‚ Checking ${changedFiles.length} changed file(s)...`);\n\n if (mode === 'MODIFIED_CODE') {\n violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head);\n } else if (mode === 'MODIFIED_FILES') {\n violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles);\n }\n }\n\n if (violations.length === 0) {\n console.log('āœ… No any/unknown keywords found');\n return { success: true };\n }\n\n reportViolations(violations, mode);\n\n return { success: false };\n}\n"]}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/dev-config/architecture/executors/validate-no-any-unknown/executor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate No Any Unknown Executor\n *\n * Validates that `any` and `unknown` TypeScript keywords are not used.\n * Uses LINE-BASED detection (not method-based) for git diff filtering.\n *\n * ============================================================================\n * VIOLATIONS (BAD) - These patterns are flagged:\n * ============================================================================\n *\n * - const x: any = ...\n * - function foo(arg: any): any { }\n * - const data = response as any;\n * - type T = any;\n * - const x: unknown = ...\n * - function foo(arg: unknown): unknown { }\n *\n * ============================================================================\n * MODES (LINE-BASED)\n * ============================================================================\n * - OFF: Skip validation entirely\n * - MODIFIED_CODE: Flag any/unknown on changed lines (lines in diff hunks)\n * - MODIFIED_FILES: Flag ALL any/unknown in files that were modified\n *\n * ============================================================================\n * ESCAPE HATCH\n * ============================================================================\n * Add comment above the violation:\n * // webpieces-disable no-any-unknown -- [your justification]\n * const x: any = ...;\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport { execSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as ts from 'typescript';\n\nexport type NoAnyUnknownMode = 'OFF' | 'MODIFIED_CODE' | 'MODIFIED_FILES';\n\nexport interface ValidateNoAnyUnknownOptions {\n mode?: NoAnyUnknownMode;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\ninterface AnyUnknownViolation {\n file: string;\n line: number;\n column: number;\n keyword: 'any' | 'unknown';\n context: string;\n}\n\n/**\n * Get changed TypeScript files between base and head (or working tree if head not specified).\n */\n// webpieces-disable max-lines-new-methods -- Git command handling with untracked files requires multiple code paths\nfunction getChangedTypeScriptFiles(workspaceRoot: string, base: string, head?: string): string[] {\n try {\n const diffTarget = head ? `${base} ${head}` : base;\n const output = execSync(`git diff --name-only ${diffTarget} -- '*.ts' '*.tsx'`, {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n });\n const changedFiles = output\n .trim()\n .split('\\n')\n .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));\n\n if (!head) {\n try {\n const untrackedOutput = execSync(`git ls-files --others --exclude-standard '*.ts' '*.tsx'`, {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n });\n const untrackedFiles = untrackedOutput\n .trim()\n .split('\\n')\n .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));\n const allFiles = new Set([...changedFiles, ...untrackedFiles]);\n return Array.from(allFiles);\n } catch {\n return changedFiles;\n }\n }\n\n return changedFiles;\n } catch {\n return [];\n }\n}\n\n/**\n * Get the diff content for a specific file.\n */\nfunction getFileDiff(workspaceRoot: string, file: string, base: string, head?: string): string {\n try {\n const diffTarget = head ? `${base} ${head}` : base;\n const diff = execSync(`git diff ${diffTarget} -- \"${file}\"`, {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n });\n\n if (!diff && !head) {\n const fullPath = path.join(workspaceRoot, file);\n if (fs.existsSync(fullPath)) {\n const isUntracked = execSync(`git ls-files --others --exclude-standard \"${file}\"`, {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n }).trim();\n\n if (isUntracked) {\n const content = fs.readFileSync(fullPath, 'utf-8');\n const lines = content.split('\\n');\n return lines.map((line) => `+${line}`).join('\\n');\n }\n }\n }\n\n return diff;\n } catch {\n return '';\n }\n}\n\n/**\n * Parse diff to extract changed line numbers (additions only - lines starting with +).\n */\nfunction getChangedLineNumbers(diffContent: string): Set<number> {\n const changedLines = new Set<number>();\n const lines = diffContent.split('\\n');\n let currentLine = 0;\n\n for (const line of lines) {\n const hunkMatch = line.match(/^@@ -\\d+(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@/);\n if (hunkMatch) {\n currentLine = parseInt(hunkMatch[1], 10);\n continue;\n }\n\n if (line.startsWith('+') && !line.startsWith('+++')) {\n changedLines.add(currentLine);\n currentLine++;\n } else if (line.startsWith('-') && !line.startsWith('---')) {\n // Deletions don't increment line number\n } else {\n currentLine++;\n }\n }\n\n return changedLines;\n}\n\n/**\n * Check if a line contains a webpieces-disable comment for no-any-unknown.\n */\nfunction hasDisableComment(lines: string[], lineNumber: number): boolean {\n const startCheck = Math.max(0, lineNumber - 5);\n for (let i = lineNumber - 2; i >= startCheck; i--) {\n const line = lines[i]?.trim() ?? '';\n if (line.startsWith('function ') || line.startsWith('class ') || line.endsWith('}')) {\n break;\n }\n if (line.includes('webpieces-disable') && line.includes('no-any-unknown')) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Get a description of the context where the any/unknown keyword appears.\n */\n// webpieces-disable max-lines-new-methods -- Context detection requires checking many AST node types\nfunction getViolationContext(node: ts.Node, sourceFile: ts.SourceFile): string {\n try {\n let current: ts.Node = node;\n while (current.parent) {\n const parent = current.parent;\n if (ts.isParameter(parent)) {\n return 'parameter type';\n }\n if (ts.isFunctionDeclaration(parent) || ts.isMethodDeclaration(parent) || ts.isArrowFunction(parent)) {\n if (parent.type === current) {\n return 'return type';\n }\n }\n if (ts.isVariableDeclaration(parent)) {\n return 'variable type';\n }\n if (ts.isPropertyDeclaration(parent) || ts.isPropertySignature(parent)) {\n return 'property type';\n }\n if (ts.isAsExpression(parent)) {\n return 'type assertion';\n }\n if (ts.isTypeAliasDeclaration(parent)) {\n return 'type alias';\n }\n if (ts.isTypeReferenceNode(parent)) {\n return 'generic argument';\n }\n if (ts.isArrayTypeNode(parent)) {\n return 'array element type';\n }\n if (ts.isUnionTypeNode(parent) || ts.isIntersectionTypeNode(parent)) {\n return 'union/intersection type';\n }\n current = parent;\n }\n return 'type position';\n } catch {\n return 'type position';\n }\n}\n\ninterface AnyUnknownInfo {\n line: number;\n column: number;\n keyword: 'any' | 'unknown';\n context: string;\n hasDisableComment: boolean;\n}\n\n/**\n * Check if a node is in a catch clause variable declaration.\n * This allows `catch (err: any)` and `catch (err: unknown)` patterns.\n */\nfunction isInCatchClause(node: ts.Node): boolean {\n let current: ts.Node | undefined = node.parent;\n while (current) {\n if (ts.isCatchClause(current)) {\n // We're somewhere in a catch clause - check if we're in the variable declaration\n const catchClause = current as ts.CatchClause;\n if (catchClause.variableDeclaration) {\n // Walk back up from the original node to see if we're part of the variable declaration\n let checkNode: ts.Node | undefined = node.parent;\n while (checkNode && checkNode !== current) {\n if (checkNode === catchClause.variableDeclaration) {\n return true;\n }\n checkNode = checkNode.parent;\n }\n }\n }\n current = current.parent;\n }\n return false;\n}\n\n/**\n * Find all `any` and `unknown` keywords in a file using AST.\n */\n// webpieces-disable max-lines-new-methods -- AST traversal with nested visitor function for keyword detection\nfunction findAnyUnknownInFile(filePath: string, workspaceRoot: string): AnyUnknownInfo[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const fileLines = content.split('\\n');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n const violations: AnyUnknownInfo[] = [];\n\n // webpieces-disable max-lines-new-methods -- AST visitor needs to handle both any and unknown keywords with full context detection\n function visit(node: ts.Node): void {\n try {\n // Detect `any` keyword\n if (node.kind === ts.SyntaxKind.AnyKeyword) {\n // Skip catch clause variable types: catch (err: any) is allowed\n if (isInCatchClause(node)) {\n ts.forEachChild(node, visit);\n return;\n }\n\n const startPos = node.getStart(sourceFile);\n if (startPos >= 0) {\n const pos = sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n const column = pos.character + 1;\n const context = getViolationContext(node, sourceFile);\n const disabled = hasDisableComment(fileLines, line);\n\n violations.push({\n line,\n column,\n keyword: 'any',\n context,\n hasDisableComment: disabled,\n });\n }\n }\n\n // Detect `unknown` keyword\n if (node.kind === ts.SyntaxKind.UnknownKeyword) {\n // Skip catch clause variable types: catch (err: unknown) is allowed\n if (isInCatchClause(node)) {\n ts.forEachChild(node, visit);\n return;\n }\n\n const startPos = node.getStart(sourceFile);\n if (startPos >= 0) {\n const pos = sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n const column = pos.character + 1;\n const context = getViolationContext(node, sourceFile);\n const disabled = hasDisableComment(fileLines, line);\n\n violations.push({\n line,\n column,\n keyword: 'unknown',\n context,\n hasDisableComment: disabled,\n });\n }\n }\n } catch {\n // Skip nodes that cause errors during analysis\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return violations;\n}\n\n/**\n * MODIFIED_CODE mode: Flag violations on changed lines in diff hunks.\n * This is LINE-BASED detection.\n */\n// webpieces-disable max-lines-new-methods -- File iteration with diff parsing and line filtering\nfunction findViolationsForModifiedCode(\n workspaceRoot: string,\n changedFiles: string[],\n base: string,\n head?: string\n): AnyUnknownViolation[] {\n const violations: AnyUnknownViolation[] = [];\n\n for (const file of changedFiles) {\n const diff = getFileDiff(workspaceRoot, file, base, head);\n const changedLines = getChangedLineNumbers(diff);\n\n if (changedLines.size === 0) continue;\n\n const allViolations = findAnyUnknownInFile(file, workspaceRoot);\n\n for (const v of allViolations) {\n if (v.hasDisableComment) continue;\n // LINE-BASED: Only include if the violation is on a changed line\n if (!changedLines.has(v.line)) continue;\n\n violations.push({\n file,\n line: v.line,\n column: v.column,\n keyword: v.keyword,\n context: v.context,\n });\n }\n }\n\n return violations;\n}\n\n/**\n * MODIFIED_FILES mode: Flag ALL violations in files that were modified.\n */\nfunction findViolationsForModifiedFiles(workspaceRoot: string, changedFiles: string[]): AnyUnknownViolation[] {\n const violations: AnyUnknownViolation[] = [];\n\n for (const file of changedFiles) {\n const allViolations = findAnyUnknownInFile(file, workspaceRoot);\n\n for (const v of allViolations) {\n if (v.hasDisableComment) continue;\n\n violations.push({\n file,\n line: v.line,\n column: v.column,\n keyword: v.keyword,\n context: v.context,\n });\n }\n }\n\n return violations;\n}\n\n/**\n * Auto-detect the base branch by finding the merge-base with origin/main.\n */\nfunction detectBase(workspaceRoot: string): string | null {\n try {\n const mergeBase = execSync('git merge-base HEAD origin/main', {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n\n if (mergeBase) {\n return mergeBase;\n }\n } catch {\n try {\n const mergeBase = execSync('git merge-base HEAD main', {\n cwd: workspaceRoot,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n\n if (mergeBase) {\n return mergeBase;\n }\n } catch {\n // Ignore\n }\n }\n return null;\n}\n\n/**\n * Report violations to console.\n */\nfunction reportViolations(violations: AnyUnknownViolation[], mode: NoAnyUnknownMode): void {\n console.error('');\n console.error('āŒ `any` and `unknown` keywords found! Use specific types instead.');\n console.error('');\n console.error('šŸ“š Avoiding any/unknown improves type safety:');\n console.error('');\n console.error(' BAD: const data: any = fetchData();');\n console.error(' GOOD: const data: UserData = fetchData();');\n console.error('');\n console.error(' BAD: function process(input: unknown): unknown { }');\n console.error(' GOOD: function process(input: ValidInput): ValidOutput { }');\n console.error('');\n\n for (const v of violations) {\n console.error(` āŒ ${v.file}:${v.line}:${v.column}`);\n console.error(` \\`${v.keyword}\\` keyword in ${v.context}`);\n }\n console.error('');\n\n console.error(' To fix: Replace with specific types or interfaces');\n console.error('');\n console.error(' Escape hatch (use sparingly):');\n console.error(' // webpieces-disable no-any-unknown -- [your reason]');\n console.error('');\n console.error(` Current mode: ${mode}`);\n console.error('');\n}\n\nexport default async function runExecutor(\n options: ValidateNoAnyUnknownOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const workspaceRoot = context.root;\n const mode: NoAnyUnknownMode = options.mode ?? 'OFF';\n\n if (mode === 'OFF') {\n console.log('\\nā­ļø Skipping no-any-unknown validation (mode: OFF)');\n console.log('');\n return { success: true };\n }\n\n console.log('\\nšŸ“ Validating No Any/Unknown\\n');\n console.log(` Mode: ${mode}`);\n\n let base = process.env['NX_BASE'];\n const head = process.env['NX_HEAD'];\n\n if (!base) {\n base = detectBase(workspaceRoot) ?? undefined;\n\n if (!base) {\n console.log('\\nā­ļø Skipping no-any-unknown validation (could not detect base branch)');\n console.log('');\n return { success: true };\n }\n }\n\n console.log(` Base: ${base}`);\n console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);\n console.log('');\n\n const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);\n\n if (changedFiles.length === 0) {\n console.log('āœ… No TypeScript files changed');\n return { success: true };\n }\n\n console.log(`šŸ“‚ Checking ${changedFiles.length} changed file(s)...`);\n\n let violations: AnyUnknownViolation[] = [];\n\n if (mode === 'MODIFIED_CODE') {\n violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head);\n } else if (mode === 'MODIFIED_FILES') {\n violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles);\n }\n\n if (violations.length === 0) {\n console.log('āœ… No any/unknown keywords found');\n return { success: true };\n }\n\n reportViolations(violations, mode);\n\n return { success: false };\n}\n"]}
@@ -21,7 +21,6 @@
21
21
  * - OFF: Skip validation entirely
22
22
  * - MODIFIED_CODE: Flag any/unknown on changed lines (lines in diff hunks)
23
23
  * - MODIFIED_FILES: Flag ALL any/unknown in files that were modified
24
- * - ALL: Flag everywhere in all TypeScript files
25
24
  *
26
25
  * ============================================================================
27
26
  * ESCAPE HATCH
@@ -37,7 +36,7 @@ import * as fs from 'fs';
37
36
  import * as path from 'path';
38
37
  import * as ts from 'typescript';
39
38
 
40
- export type NoAnyUnknownMode = 'OFF' | 'MODIFIED_CODE' | 'MODIFIED_FILES' | 'ALL';
39
+ export type NoAnyUnknownMode = 'OFF' | 'MODIFIED_CODE' | 'MODIFIED_FILES';
41
40
 
42
41
  export interface ValidateNoAnyUnknownOptions {
43
42
  mode?: NoAnyUnknownMode;
@@ -94,24 +93,6 @@ function getChangedTypeScriptFiles(workspaceRoot: string, base: string, head?: s
94
93
  }
95
94
  }
96
95
 
97
- /**
98
- * Get all TypeScript files in the workspace using git ls-files (excluding tests).
99
- */
100
- function getAllTypeScriptFiles(workspaceRoot: string): string[] {
101
- try {
102
- const output = execSync(`git ls-files '*.ts' '*.tsx'`, {
103
- cwd: workspaceRoot,
104
- encoding: 'utf-8',
105
- });
106
- return output
107
- .trim()
108
- .split('\n')
109
- .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
110
- } catch {
111
- return [];
112
- }
113
- }
114
-
115
96
  /**
116
97
  * Get the diff content for a specific file.
117
98
  */
@@ -244,6 +225,32 @@ interface AnyUnknownInfo {
244
225
  hasDisableComment: boolean;
245
226
  }
246
227
 
228
+ /**
229
+ * Check if a node is in a catch clause variable declaration.
230
+ * This allows `catch (err: any)` and `catch (err: unknown)` patterns.
231
+ */
232
+ function isInCatchClause(node: ts.Node): boolean {
233
+ let current: ts.Node | undefined = node.parent;
234
+ while (current) {
235
+ if (ts.isCatchClause(current)) {
236
+ // We're somewhere in a catch clause - check if we're in the variable declaration
237
+ const catchClause = current as ts.CatchClause;
238
+ if (catchClause.variableDeclaration) {
239
+ // Walk back up from the original node to see if we're part of the variable declaration
240
+ let checkNode: ts.Node | undefined = node.parent;
241
+ while (checkNode && checkNode !== current) {
242
+ if (checkNode === catchClause.variableDeclaration) {
243
+ return true;
244
+ }
245
+ checkNode = checkNode.parent;
246
+ }
247
+ }
248
+ }
249
+ current = current.parent;
250
+ }
251
+ return false;
252
+ }
253
+
247
254
  /**
248
255
  * Find all `any` and `unknown` keywords in a file using AST.
249
256
  */
@@ -263,6 +270,12 @@ function findAnyUnknownInFile(filePath: string, workspaceRoot: string): AnyUnkno
263
270
  try {
264
271
  // Detect `any` keyword
265
272
  if (node.kind === ts.SyntaxKind.AnyKeyword) {
273
+ // Skip catch clause variable types: catch (err: any) is allowed
274
+ if (isInCatchClause(node)) {
275
+ ts.forEachChild(node, visit);
276
+ return;
277
+ }
278
+
266
279
  const startPos = node.getStart(sourceFile);
267
280
  if (startPos >= 0) {
268
281
  const pos = sourceFile.getLineAndCharacterOfPosition(startPos);
@@ -283,6 +296,12 @@ function findAnyUnknownInFile(filePath: string, workspaceRoot: string): AnyUnkno
283
296
 
284
297
  // Detect `unknown` keyword
285
298
  if (node.kind === ts.SyntaxKind.UnknownKeyword) {
299
+ // Skip catch clause variable types: catch (err: unknown) is allowed
300
+ if (isInCatchClause(node)) {
301
+ ts.forEachChild(node, visit);
302
+ return;
303
+ }
304
+
286
305
  const startPos = node.getStart(sourceFile);
287
306
  if (startPos >= 0) {
288
307
  const pos = sourceFile.getLineAndCharacterOfPosition(startPos);
@@ -375,14 +394,6 @@ function findViolationsForModifiedFiles(workspaceRoot: string, changedFiles: str
375
394
  return violations;
376
395
  }
377
396
 
378
- /**
379
- * ALL mode: Flag violations in all TypeScript files.
380
- */
381
- function findViolationsForAll(workspaceRoot: string): AnyUnknownViolation[] {
382
- const allFiles = getAllTypeScriptFiles(workspaceRoot);
383
- return findViolationsForModifiedFiles(workspaceRoot, allFiles);
384
- }
385
-
386
397
  /**
387
398
  * Auto-detect the base branch by finding the merge-base with origin/main.
388
399
  */
@@ -462,44 +473,38 @@ export default async function runExecutor(
462
473
  console.log('\nšŸ“ Validating No Any/Unknown\n');
463
474
  console.log(` Mode: ${mode}`);
464
475
 
465
- let violations: AnyUnknownViolation[] = [];
476
+ let base = process.env['NX_BASE'];
477
+ const head = process.env['NX_HEAD'];
466
478
 
467
- if (mode === 'ALL') {
468
- console.log(' Scope: All tracked TypeScript files');
469
- console.log('');
470
- violations = findViolationsForAll(workspaceRoot);
471
- } else {
472
- let base = process.env['NX_BASE'];
473
- const head = process.env['NX_HEAD'];
479
+ if (!base) {
480
+ base = detectBase(workspaceRoot) ?? undefined;
474
481
 
475
482
  if (!base) {
476
- base = detectBase(workspaceRoot) ?? undefined;
477
-
478
- if (!base) {
479
- console.log('\nā­ļø Skipping no-any-unknown validation (could not detect base branch)');
480
- console.log('');
481
- return { success: true };
482
- }
483
+ console.log('\nā­ļø Skipping no-any-unknown validation (could not detect base branch)');
484
+ console.log('');
485
+ return { success: true };
483
486
  }
487
+ }
484
488
 
485
- console.log(` Base: ${base}`);
486
- console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
487
- console.log('');
489
+ console.log(` Base: ${base}`);
490
+ console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
491
+ console.log('');
488
492
 
489
- const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
493
+ const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
490
494
 
491
- if (changedFiles.length === 0) {
492
- console.log('āœ… No TypeScript files changed');
493
- return { success: true };
494
- }
495
+ if (changedFiles.length === 0) {
496
+ console.log('āœ… No TypeScript files changed');
497
+ return { success: true };
498
+ }
495
499
 
496
- console.log(`šŸ“‚ Checking ${changedFiles.length} changed file(s)...`);
500
+ console.log(`šŸ“‚ Checking ${changedFiles.length} changed file(s)...`);
497
501
 
498
- if (mode === 'MODIFIED_CODE') {
499
- violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head);
500
- } else if (mode === 'MODIFIED_FILES') {
501
- violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles);
502
- }
502
+ let violations: AnyUnknownViolation[] = [];
503
+
504
+ if (mode === 'MODIFIED_CODE') {
505
+ violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head);
506
+ } else if (mode === 'MODIFIED_FILES') {
507
+ violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles);
503
508
  }
504
509
 
505
510
  if (violations.length === 0) {
@@ -6,8 +6,8 @@
6
6
  "properties": {
7
7
  "mode": {
8
8
  "type": "string",
9
- "enum": ["OFF", "MODIFIED_CODE", "MODIFIED_FILES", "ALL"],
10
- "description": "OFF: skip validation. MODIFIED_CODE: only changed lines in diff. MODIFIED_FILES: all in modified files. ALL: everywhere. Disallows `any` and `unknown` TypeScript keywords.",
9
+ "enum": ["OFF", "MODIFIED_CODE", "MODIFIED_FILES"],
10
+ "description": "OFF: skip validation. MODIFIED_CODE: only changed lines in diff. MODIFIED_FILES: all in modified files. Disallows `any` and `unknown` TypeScript keywords.",
11
11
  "default": "OFF"
12
12
  }
13
13
  },
@@ -65,7 +65,6 @@
65
65
  * - NEW_METHODS: Only validate in new methods (detected via git diff)
66
66
  * - MODIFIED_AND_NEW_METHODS: Validate in new methods + methods with changes
67
67
  * - MODIFIED_FILES: Validate all violations in modified files
68
- * - ALL: Validate all violations in all TypeScript files
69
68
  *
70
69
  * ============================================================================
71
70
  * ESCAPE HATCH
@@ -80,7 +79,7 @@
80
79
  * - Legacy code being incrementally migrated
81
80
  */
82
81
  import type { ExecutorContext } from '@nx/devkit';
83
- export type NoInlineTypesMode = 'OFF' | 'NEW_METHODS' | 'MODIFIED_AND_NEW_METHODS' | 'MODIFIED_FILES' | 'ALL';
82
+ export type NoInlineTypesMode = 'OFF' | 'NEW_METHODS' | 'MODIFIED_AND_NEW_METHODS' | 'MODIFIED_FILES';
84
83
  export interface ValidateNoInlineTypesOptions {
85
84
  mode?: NoInlineTypesMode;
86
85
  }
@@ -66,7 +66,6 @@
66
66
  * - NEW_METHODS: Only validate in new methods (detected via git diff)
67
67
  * - MODIFIED_AND_NEW_METHODS: Validate in new methods + methods with changes
68
68
  * - MODIFIED_FILES: Validate all violations in modified files
69
- * - ALL: Validate all violations in all TypeScript files
70
69
  *
71
70
  * ============================================================================
72
71
  * ESCAPE HATCH
@@ -125,24 +124,6 @@ function getChangedTypeScriptFiles(workspaceRoot, base, head) {
125
124
  return [];
126
125
  }
127
126
  }
128
- /**
129
- * Get all TypeScript files in the workspace using git ls-files (excluding tests).
130
- */
131
- function getAllTypeScriptFiles(workspaceRoot) {
132
- try {
133
- const output = (0, child_process_1.execSync)(`git ls-files '*.ts' '*.tsx'`, {
134
- cwd: workspaceRoot,
135
- encoding: 'utf-8',
136
- });
137
- return output
138
- .trim()
139
- .split('\n')
140
- .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
141
- }
142
- catch {
143
- return [];
144
- }
145
- }
146
127
  /**
147
128
  * Get the diff content for a specific file.
148
129
  */
@@ -560,13 +541,6 @@ function findViolationsForModifiedFiles(workspaceRoot, changedFiles) {
560
541
  }
561
542
  return violations;
562
543
  }
563
- /**
564
- * Find all violations in all files (ALL mode).
565
- */
566
- function findViolationsForAll(workspaceRoot) {
567
- const allFiles = getAllTypeScriptFiles(workspaceRoot);
568
- return findViolationsForModifiedFiles(workspaceRoot, allFiles);
569
- }
570
544
  /**
571
545
  * Auto-detect the base branch by finding the merge-base with origin/main.
572
546
  */
@@ -638,41 +612,34 @@ async function runExecutor(options, context) {
638
612
  }
639
613
  console.log('\nšŸ“ Validating No Inline Types\n');
640
614
  console.log(` Mode: ${mode}`);
641
- let violations = [];
642
- if (mode === 'ALL') {
643
- console.log(' Scope: All tracked TypeScript files');
644
- console.log('');
645
- violations = findViolationsForAll(workspaceRoot);
646
- }
647
- else {
648
- let base = process.env['NX_BASE'];
649
- const head = process.env['NX_HEAD'];
615
+ let base = process.env['NX_BASE'];
616
+ const head = process.env['NX_HEAD'];
617
+ if (!base) {
618
+ base = detectBase(workspaceRoot) ?? undefined;
650
619
  if (!base) {
651
- base = detectBase(workspaceRoot) ?? undefined;
652
- if (!base) {
653
- console.log('\nā­ļø Skipping no-inline-types validation (could not detect base branch)');
654
- console.log('');
655
- return { success: true };
656
- }
657
- }
658
- console.log(` Base: ${base}`);
659
- console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
660
- console.log('');
661
- const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
662
- if (changedFiles.length === 0) {
663
- console.log('āœ… No TypeScript files changed');
620
+ console.log('\nā­ļø Skipping no-inline-types validation (could not detect base branch)');
621
+ console.log('');
664
622
  return { success: true };
665
623
  }
666
- console.log(`šŸ“‚ Checking ${changedFiles.length} changed file(s)...`);
667
- if (mode === 'NEW_METHODS') {
668
- violations = findViolationsForNewMethods(workspaceRoot, changedFiles, base, head);
669
- }
670
- else if (mode === 'MODIFIED_AND_NEW_METHODS') {
671
- violations = findViolationsForModifiedAndNewMethods(workspaceRoot, changedFiles, base, head);
672
- }
673
- else if (mode === 'MODIFIED_FILES') {
674
- violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles);
675
- }
624
+ }
625
+ console.log(` Base: ${base}`);
626
+ console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
627
+ console.log('');
628
+ const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
629
+ if (changedFiles.length === 0) {
630
+ console.log('āœ… No TypeScript files changed');
631
+ return { success: true };
632
+ }
633
+ console.log(`šŸ“‚ Checking ${changedFiles.length} changed file(s)...`);
634
+ let violations = [];
635
+ if (mode === 'NEW_METHODS') {
636
+ violations = findViolationsForNewMethods(workspaceRoot, changedFiles, base, head);
637
+ }
638
+ else if (mode === 'MODIFIED_AND_NEW_METHODS') {
639
+ violations = findViolationsForModifiedAndNewMethods(workspaceRoot, changedFiles, base, head);
640
+ }
641
+ else if (mode === 'MODIFIED_FILES') {
642
+ violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles);
676
643
  }
677
644
  if (violations.length === 0) {
678
645
  console.log('āœ… No inline type literals found');