@webpieces/code-rules 0.3.195 → 0.3.197

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 (44) hide show
  1. package/package.json +2 -2
  2. package/src/diff-utils.d.ts +3 -22
  3. package/src/diff-utils.js +9 -116
  4. package/src/diff-utils.js.map +1 -1
  5. package/src/validate-catch-error-pattern.d.ts +1 -1
  6. package/src/validate-catch-error-pattern.js +7 -152
  7. package/src/validate-catch-error-pattern.js.map +1 -1
  8. package/src/validate-dtos.d.ts +1 -1
  9. package/src/validate-dtos.js +6 -141
  10. package/src/validate-dtos.js.map +1 -1
  11. package/src/validate-modified-files.js +3 -87
  12. package/src/validate-modified-files.js.map +1 -1
  13. package/src/validate-modified-methods.d.ts +1 -1
  14. package/src/validate-modified-methods.js +7 -197
  15. package/src/validate-modified-methods.js.map +1 -1
  16. package/src/validate-new-methods.js +4 -164
  17. package/src/validate-new-methods.js.map +1 -1
  18. package/src/validate-no-any-unknown.d.ts +1 -1
  19. package/src/validate-no-any-unknown.js +7 -143
  20. package/src/validate-no-any-unknown.js.map +1 -1
  21. package/src/validate-no-destructure.d.ts +1 -1
  22. package/src/validate-no-destructure.js +7 -143
  23. package/src/validate-no-destructure.js.map +1 -1
  24. package/src/validate-no-direct-api-resolver.d.ts +1 -1
  25. package/src/validate-no-direct-api-resolver.js +10 -89
  26. package/src/validate-no-direct-api-resolver.js.map +1 -1
  27. package/src/validate-no-implicit-any.d.ts +1 -1
  28. package/src/validate-no-implicit-any.js +6 -94
  29. package/src/validate-no-implicit-any.js.map +1 -1
  30. package/src/validate-no-inline-types.d.ts +1 -1
  31. package/src/validate-no-inline-types.js +10 -174
  32. package/src/validate-no-inline-types.js.map +1 -1
  33. package/src/validate-no-symbol-di-tokens.d.ts +1 -1
  34. package/src/validate-no-symbol-di-tokens.js +6 -130
  35. package/src/validate-no-symbol-di-tokens.js.map +1 -1
  36. package/src/validate-no-unmanaged-exceptions.d.ts +1 -1
  37. package/src/validate-no-unmanaged-exceptions.js +7 -152
  38. package/src/validate-no-unmanaged-exceptions.js.map +1 -1
  39. package/src/validate-prisma-converters.d.ts +1 -1
  40. package/src/validate-prisma-converters.js +10 -89
  41. package/src/validate-prisma-converters.js.map +1 -1
  42. package/src/validate-return-types.d.ts +1 -1
  43. package/src/validate-return-types.js +10 -174
  44. package/src/validate-return-types.js.map +1 -1
@@ -25,7 +25,7 @@
25
25
  * - OFF: Skip validation entirely
26
26
  * - MODIFIED_CODE: Flag violations on changed lines (lines in diff hunks)
27
27
  * - NEW_AND_MODIFIED_METHODS: Flag violations in new/modified method/route scopes
28
- * - MODIFIED_FILES: Flag ALL violations in files that were modified
28
+ * - NEW_AND_MODIFIED_FILES: Flag ALL violations in files that were modified
29
29
  *
30
30
  * ============================================================================
31
31
  * ESCAPE HATCH
@@ -37,56 +37,12 @@
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
38
  exports.NoDirectApiResolverValidator = void 0;
39
39
  const tslib_1 = require("tslib");
40
- const child_process_1 = require("child_process");
41
40
  const fs = tslib_1.__importStar(require("fs"));
42
41
  const path = tslib_1.__importStar(require("path"));
43
42
  const ts = tslib_1.__importStar(require("typescript"));
44
- const diff_utils_1 = require("./diff-utils");
45
43
  const rules_config_1 = require("@webpieces/rules-config");
46
44
  const code_validator_1 = require("./code-validator");
47
45
  const resolve_mode_1 = require("./resolve-mode");
48
- /**
49
- * Get changed TypeScript files between base and head (or working tree if head not specified).
50
- */
51
- // webpieces-disable max-lines-new-methods -- Git command handling with untracked files requires multiple code paths
52
- function getChangedTypeScriptFiles(workspaceRoot, base, head) {
53
- // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
54
- try {
55
- const diffTarget = head ? `${base} ${head}` : base;
56
- const output = (0, child_process_1.execSync)(`git diff --name-only ${diffTarget} -- '*.ts' '*.tsx'`, {
57
- cwd: workspaceRoot,
58
- encoding: 'utf-8',
59
- });
60
- const changedFiles = output
61
- .trim()
62
- .split('\n')
63
- .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
64
- if (!head) {
65
- // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
66
- try {
67
- const untrackedOutput = (0, child_process_1.execSync)(`git ls-files --others --exclude-standard '*.ts' '*.tsx'`, {
68
- cwd: workspaceRoot,
69
- encoding: 'utf-8',
70
- });
71
- const untrackedFiles = untrackedOutput
72
- .trim()
73
- .split('\n')
74
- .filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
75
- const allFiles = new Set([...changedFiles, ...untrackedFiles]);
76
- return Array.from(allFiles);
77
- }
78
- catch (err) {
79
- //const error = toError(err);
80
- return changedFiles;
81
- }
82
- }
83
- return changedFiles;
84
- }
85
- catch (err) {
86
- //const error = toError(err);
87
- return [];
88
- }
89
- }
90
46
  /**
91
47
  * Check if a line contains a webpieces-disable comment for no-direct-api-resolver.
92
48
  */
@@ -103,41 +59,6 @@ function hasDisableComment(lines, lineNumber) {
103
59
  }
104
60
  return false;
105
61
  }
106
- /**
107
- * Auto-detect the base branch by finding the merge-base with origin/main.
108
- */
109
- function detectBase(workspaceRoot) {
110
- // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
111
- try {
112
- const mergeBase = (0, child_process_1.execSync)('git merge-base HEAD origin/main', {
113
- cwd: workspaceRoot,
114
- encoding: 'utf-8',
115
- stdio: ['pipe', 'pipe', 'pipe'],
116
- }).trim();
117
- if (mergeBase) {
118
- return mergeBase;
119
- }
120
- }
121
- catch (err) {
122
- //const error = toError(err);
123
- // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
124
- try {
125
- const mergeBase = (0, child_process_1.execSync)('git merge-base HEAD main', {
126
- cwd: workspaceRoot,
127
- encoding: 'utf-8',
128
- stdio: ['pipe', 'pipe', 'pipe'],
129
- }).trim();
130
- if (mergeBase) {
131
- return mergeBase;
132
- }
133
- }
134
- catch (err2) {
135
- //const error2 = toError(err2);
136
- // Ignore
137
- }
138
- }
139
- return null;
140
- }
141
62
  /**
142
63
  * Find inject(XxxApi) calls in *.routes.ts files.
143
64
  * Flags any CallExpression where callee is `inject` and the first argument is an identifier ending with `Api`.
@@ -255,8 +176,8 @@ function findViolationsInFile(filePath, workspaceRoot, disableAllowed) {
255
176
  function findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head, disableAllowed) {
256
177
  const violations = [];
257
178
  for (const file of changedFiles) {
258
- const diff = (0, diff_utils_1.getFileDiff)(workspaceRoot, file, base, head);
259
- const changedLines = (0, diff_utils_1.getChangedLineNumbers)(diff);
179
+ const diff = (0, rules_config_1.getFileDiff)(workspaceRoot, file, base, head);
180
+ const changedLines = (0, rules_config_1.getChangedLineNumbers)(diff);
260
181
  if (changedLines.size === 0)
261
182
  continue;
262
183
  const allViolations = findViolationsInFile(file, workspaceRoot, disableAllowed);
@@ -277,7 +198,7 @@ function findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head,
277
198
  return violations;
278
199
  }
279
200
  /**
280
- * MODIFIED_FILES mode: Flag ALL violations in files that were modified.
201
+ * NEW_AND_MODIFIED_FILES mode: Flag ALL violations in files that were modified.
281
202
  */
282
203
  function findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed) {
283
204
  const violations = [];
@@ -391,9 +312,9 @@ function findMethodRanges(filePath, workspaceRoot) {
391
312
  function findViolationsForModifiedMethods(workspaceRoot, changedFiles, base, head, disableAllowed) {
392
313
  const violations = [];
393
314
  for (const file of changedFiles) {
394
- const diff = (0, diff_utils_1.getFileDiff)(workspaceRoot, file, base, head);
395
- const changedLines = (0, diff_utils_1.getChangedLineNumbers)(diff);
396
- const newMethodNames = (0, diff_utils_1.findNewMethodSignaturesInDiff)(diff);
315
+ const diff = (0, rules_config_1.getFileDiff)(workspaceRoot, file, base, head);
316
+ const changedLines = (0, rules_config_1.getChangedLineNumbers)(diff);
317
+ const newMethodNames = (0, rules_config_1.findNewMethodSignaturesInDiff)(diff);
397
318
  if (changedLines.size === 0 && newMethodNames.size === 0)
398
319
  continue;
399
320
  if (file.endsWith('.routes.ts')) {
@@ -541,7 +462,7 @@ async function runValidatorImpl(options, workspaceRoot) {
541
462
  let base = process.env['NX_BASE'];
542
463
  const head = process.env['NX_HEAD'];
543
464
  if (!base) {
544
- base = detectBase(workspaceRoot) ?? undefined;
465
+ base = (0, rules_config_1.detectBase)(workspaceRoot) ?? undefined;
545
466
  if (!base) {
546
467
  console.log('\n\u23ed\ufe0f Skipping no-direct-api-resolver validation (could not detect base branch)');
547
468
  console.log('');
@@ -551,7 +472,7 @@ async function runValidatorImpl(options, workspaceRoot) {
551
472
  console.log(` Base: ${base}`);
552
473
  console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
553
474
  console.log('');
554
- const allChangedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
475
+ const allChangedFiles = (0, rules_config_1.getChangedFiles)(workspaceRoot, base, head);
555
476
  const scopedFiles = filterByEnforcePaths(allChangedFiles, options.enforcePaths);
556
477
  const changedFiles = filterRelevantFiles(scopedFiles);
557
478
  if (changedFiles.length === 0) {
@@ -566,7 +487,7 @@ async function runValidatorImpl(options, workspaceRoot) {
566
487
  else if (mode === 'NEW_AND_MODIFIED_METHODS') {
567
488
  violations = findViolationsForModifiedMethods(workspaceRoot, changedFiles, base, head, disableAllowed);
568
489
  }
569
- else if (mode === 'MODIFIED_FILES') {
490
+ else if (mode === 'NEW_AND_MODIFIED_FILES') {
570
491
  violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed);
571
492
  }
572
493
  if (violations.length === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"validate-no-direct-api-resolver.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/validate-no-direct-api-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate No Direct API in Resolver Executor\n *\n * Validates two Angular anti-patterns using LINE-BASED detection:\n *\n * ============================================================================\n * VIOLATIONS (BAD) - These patterns are flagged:\n * ============================================================================\n *\n * 1. In *.routes.ts files: inject(XxxApi) — resolvers should inject services, not APIs directly\n * 2. In *.component.ts files: this.<field>.snapshot.data — components should subscribe to\n * service BehaviorSubjects, not read route snapshot data\n *\n * ============================================================================\n * CORRECT PATTERNS (GOOD)\n * ============================================================================\n *\n * 1. In resolvers: inject(XxxService) which calls the API internally\n * 2. In components: this.myService.someObservable$ (subscribe to service BehaviorSubjects)\n *\n * ============================================================================\n * MODES (LINE-BASED)\n * ============================================================================\n * - OFF: Skip validation entirely\n * - MODIFIED_CODE: Flag violations on changed lines (lines in diff hunks)\n * - NEW_AND_MODIFIED_METHODS: Flag violations in new/modified method/route scopes\n * - MODIFIED_FILES: Flag ALL violations in files that were modified\n *\n * ============================================================================\n * ESCAPE HATCH\n * ============================================================================\n * Add comment above the violation:\n * // webpieces-disable no-direct-api-resolver -- [your justification]\n * const myApi = inject(MyApi);\n */\n\nimport { execSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as ts from 'typescript';\nimport { getFileDiff, getChangedLineNumbers, findNewMethodSignaturesInDiff } from './diff-utils';\nimport { hasDisable, RULE_NAMES, AngularNoDirectApiInResolverConfig, DirectApiResolverMode } from '@webpieces/rules-config';\nimport { CodeValidator, ExecutorResult } from './code-validator';\nimport { shouldSkipRule } from './resolve-mode';\n\ninterface Violation {\n file: string;\n line: number;\n column: number;\n context: string;\n}\n\ninterface ViolationInfo {\n line: number;\n column: number;\n context: string;\n hasDisableComment: boolean;\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 // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\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 // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\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 (err: unknown) {\n //const error = toError(err);\n return changedFiles;\n }\n }\n\n return changedFiles;\n } catch (err: unknown) {\n //const error = toError(err);\n return [];\n }\n}\n\n/**\n * Check if a line contains a webpieces-disable comment for no-direct-api-resolver.\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 (hasDisable(line, RULE_NAMES.NO_DIRECT_API_RESOLVER)) {\n return true;\n }\n }\n return false;\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 // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\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 (err: unknown) {\n //const error = toError(err);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\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 (err2: unknown) {\n //const error2 = toError(err2);\n // Ignore\n }\n }\n return null;\n}\n\n/**\n * Find inject(XxxApi) calls in *.routes.ts files.\n * Flags any CallExpression where callee is `inject` and the first argument is an identifier ending with `Api`.\n */\nfunction findDirectApiInjections(filePath: string, workspaceRoot: string, disableAllowed: boolean): ViolationInfo[] {\n if (!filePath.endsWith('.routes.ts')) return [];\n\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: ViolationInfo[] = [];\n\n function visit(node: ts.Node): void {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n if (ts.isCallExpression(node)) {\n const callee = node.expression;\n if (ts.isIdentifier(callee) && callee.text === 'inject') {\n const firstArg = node.arguments[0];\n if (firstArg && ts.isIdentifier(firstArg) && firstArg.text.endsWith('Api')) {\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 disabled = hasDisableComment(fileLines, line);\n\n if (!disableAllowed && disabled) {\n violations.push({ line, column, context: `inject(${firstArg.text}) in route resolver`, hasDisableComment: false });\n } else {\n violations.push({ line, column, context: `inject(${firstArg.text}) in route resolver`, hasDisableComment: disabled });\n }\n }\n }\n }\n }\n } catch (err: unknown) {\n //const error = toError(err);\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 * Find this.<field>.snapshot.data access patterns in *.component.ts files.\n * Flags PropertyAccessExpression chains: this.<anything>.snapshot.data\n */\nfunction findSnapshotDataAccess(filePath: string, workspaceRoot: string, disableAllowed: boolean): ViolationInfo[] {\n if (!filePath.endsWith('.component.ts')) return [];\n\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: ViolationInfo[] = [];\n\n function visit(node: ts.Node): void {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n // Looking for: this.<field>.snapshot.data\n // AST shape: PropertyAccessExpression(.data) -> PropertyAccessExpression(.snapshot) -> PropertyAccessExpression(.<field>) -> this\n if (ts.isPropertyAccessExpression(node) && node.name.text === 'data') {\n const snapshotAccess = node.expression;\n if (ts.isPropertyAccessExpression(snapshotAccess) && snapshotAccess.name.text === 'snapshot') {\n const fieldAccess = snapshotAccess.expression;\n if (ts.isPropertyAccessExpression(fieldAccess)) {\n const receiver = fieldAccess.expression;\n if (receiver.kind === ts.SyntaxKind.ThisKeyword) {\n const fieldName = fieldAccess.name.text;\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 disabled = hasDisableComment(fileLines, line);\n\n if (!disableAllowed && disabled) {\n violations.push({ line, column, context: `this.${fieldName}.snapshot.data in component`, hasDisableComment: false });\n } else {\n violations.push({ line, column, context: `this.${fieldName}.snapshot.data in component`, hasDisableComment: disabled });\n }\n }\n }\n }\n }\n }\n } catch (err: unknown) {\n //const error = toError(err);\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 * Find all violations in a file (both inject(Api) and snapshot.data patterns).\n */\nfunction findViolationsInFile(filePath: string, workspaceRoot: string, disableAllowed: boolean): ViolationInfo[] {\n const apiViolations = findDirectApiInjections(filePath, workspaceRoot, disableAllowed);\n const snapshotViolations = findSnapshotDataAccess(filePath, workspaceRoot, disableAllowed);\n return [...apiViolations, ...snapshotViolations];\n}\n\n/**\n * MODIFIED_CODE mode: Flag violations on changed lines in diff hunks.\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 | undefined,\n disableAllowed: boolean\n): Violation[] {\n const violations: Violation[] = [];\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 = findViolationsInFile(file, workspaceRoot, disableAllowed);\n\n for (const v of allViolations) {\n if (disableAllowed && 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 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[], disableAllowed: boolean): Violation[] {\n const violations: Violation[] = [];\n\n for (const file of changedFiles) {\n const allViolations = findViolationsInFile(file, workspaceRoot, disableAllowed);\n\n for (const v of allViolations) {\n if (disableAllowed && v.hasDisableComment) continue;\n\n violations.push({\n file,\n line: v.line,\n column: v.column,\n context: v.context,\n });\n }\n }\n\n return violations;\n}\n\ninterface RangeInfo {\n name: string;\n startLine: number;\n endLine: number;\n}\n\n/**\n * Find route object ranges in *.routes.ts files.\n * A route object is an ObjectLiteralExpression that contains (directly or in descendants)\n * a `resolve` property. Returns the line range of each such top-level route object.\n */\nfunction findRouteObjectRanges(filePath: string, workspaceRoot: string): RangeInfo[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n const ranges: RangeInfo[] = [];\n\n function hasResolveProperty(node: ts.Node): boolean {\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && node.name.text === 'resolve') {\n return true;\n }\n let found = false;\n ts.forEachChild(node, (child) => {\n if (hasResolveProperty(child)) {\n found = true;\n }\n });\n return found;\n }\n\n function visitTopLevel(node: ts.Node): void {\n if (ts.isObjectLiteralExpression(node) && hasResolveProperty(node)) {\n const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n ranges.push({\n name: `route@${start.line + 1}`,\n startLine: start.line + 1,\n endLine: end.line + 1,\n });\n return;\n }\n ts.forEachChild(node, visitTopLevel);\n }\n\n visitTopLevel(sourceFile);\n return ranges;\n}\n\n/**\n * Find method/function ranges in *.component.ts files.\n * Returns ranges for class methods, function declarations, and arrow functions in variable declarations.\n */\nfunction findMethodRanges(filePath: string, workspaceRoot: string): RangeInfo[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n const ranges: RangeInfo[] = [];\n\n function visit(node: ts.Node): void {\n let methodName: string | undefined;\n let startLine: number | undefined;\n let endLine: number | undefined;\n\n if (ts.isMethodDeclaration(node) && node.name) {\n methodName = node.name.getText(sourceFile);\n const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n startLine = start.line + 1;\n endLine = end.line + 1;\n } else if (ts.isFunctionDeclaration(node) && node.name) {\n methodName = node.name.getText(sourceFile);\n const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n startLine = start.line + 1;\n endLine = end.line + 1;\n } else if (ts.isArrowFunction(node)) {\n if (ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {\n methodName = node.parent.name.getText(sourceFile);\n const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n startLine = start.line + 1;\n endLine = end.line + 1;\n }\n }\n\n if (methodName && startLine !== undefined && endLine !== undefined) {\n ranges.push({ name: methodName, startLine, endLine });\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return ranges;\n}\n\n/**\n * NEW_AND_MODIFIED_METHODS mode: Flag violations in new/modified method/route scopes.\n * - For *.routes.ts: If any line in a route object is changed, flag all inject(XxxApi) violations in that route\n * - For *.component.ts: If a method is new/modified, flag all snapshot.data violations in that method\n */\n// webpieces-disable max-lines-new-methods -- Method-scoped validation with route objects and component methods\nfunction findViolationsForModifiedMethods(\n workspaceRoot: string,\n changedFiles: string[],\n base: string,\n head: string | undefined,\n disableAllowed: boolean\n): Violation[] {\n const violations: Violation[] = [];\n\n for (const file of changedFiles) {\n const diff = getFileDiff(workspaceRoot, file, base, head);\n const changedLines = getChangedLineNumbers(diff);\n const newMethodNames = findNewMethodSignaturesInDiff(diff);\n\n if (changedLines.size === 0 && newMethodNames.size === 0) continue;\n\n if (file.endsWith('.routes.ts')) {\n const routeRanges = findRouteObjectRanges(file, workspaceRoot);\n const allViolations = findDirectApiInjections(file, workspaceRoot, disableAllowed);\n\n for (const range of routeRanges) {\n let rangeHasChanges = false;\n for (let line = range.startLine; line <= range.endLine; line++) {\n if (changedLines.has(line)) {\n rangeHasChanges = true;\n break;\n }\n }\n if (!rangeHasChanges) continue;\n\n for (const v of allViolations) {\n if (disableAllowed && v.hasDisableComment) continue;\n if (v.line >= range.startLine && v.line <= range.endLine) {\n violations.push({\n file,\n line: v.line,\n column: v.column,\n context: v.context,\n });\n }\n }\n }\n } else if (file.endsWith('.component.ts')) {\n const methodRanges = findMethodRanges(file, workspaceRoot);\n const allViolations = findSnapshotDataAccess(file, workspaceRoot, disableAllowed);\n\n for (const range of methodRanges) {\n const isNewMethod = newMethodNames.has(range.name);\n let rangeHasChanges = false;\n if (!isNewMethod) {\n for (let line = range.startLine; line <= range.endLine; line++) {\n if (changedLines.has(line)) {\n rangeHasChanges = true;\n break;\n }\n }\n }\n if (!isNewMethod && !rangeHasChanges) continue;\n\n for (const v of allViolations) {\n if (disableAllowed && v.hasDisableComment) continue;\n if (v.line >= range.startLine && v.line <= range.endLine) {\n violations.push({\n file,\n line: v.line,\n column: v.column,\n context: v.context,\n });\n }\n }\n }\n }\n }\n\n return violations;\n}\n\n/**\n * Report violations to console.\n */\n// webpieces-disable max-lines-new-methods -- Console output with examples and escape hatch information\nfunction reportViolations(violations: Violation[], mode: DirectApiResolverMode, disableAllowed: boolean): void {\n console.error('');\n console.error('\\u274c Direct API usage in resolvers or snapshot.data in components found!');\n console.error('');\n console.error('\\ud83d\\udcda Resolvers should use services, and components should subscribe to service observables:');\n console.error('');\n console.error(' BAD (in *.routes.ts resolver):');\n console.error(' const myApi = inject(MyApi);');\n console.error(' resolve: () => inject(MyApi).fetchData()');\n console.error('');\n console.error(' GOOD (in *.routes.ts resolver):');\n console.error(' const myService = inject(MyService);');\n console.error(' resolve: () => inject(MyService).loadData()');\n console.error('');\n console.error(' BAD (in *.component.ts):');\n console.error(' const data = this.route.snapshot.data;');\n console.error('');\n console.error(' GOOD (in *.component.ts):');\n console.error(' this.myService.data$.subscribe(data => ...)');\n console.error('');\n\n for (const v of violations) {\n console.error(` \\u274c ${v.file}:${v.line}:${v.column}`);\n console.error(` ${v.context}`);\n }\n console.error('');\n\n if (disableAllowed) {\n console.error(' Escape hatch (use sparingly):');\n console.error(' // webpieces-disable no-direct-api-resolver -- [your reason]');\n } else {\n console.error(' Escape hatch: DISABLED (disableAllowed: false)');\n console.error(' Disable comments are ignored. Fix the pattern directly.');\n }\n console.error('');\n console.error(` Current mode: ${mode}`);\n console.error('');\n}\n\n/**\n * Resolve mode considering ignoreModifiedUntilEpoch override.\n * When active, downgrades to OFF. When expired, logs a warning.\n */\nfunction resolveMode(normalMode: DirectApiResolverMode, epoch: number | undefined, branchPattern: string | undefined): DirectApiResolverMode {\n if (normalMode === 'OFF') {\n return normalMode;\n }\n const skip = shouldSkipRule(epoch, branchPattern);\n if (skip.skip) {\n console.log(`\\n\\u23ed\\ufe0f Skipping no-direct-api-resolver validation (${skip.reason})`);\n console.log('');\n return 'OFF';\n }\n return normalMode;\n}\n\n/**\n * Filter changed files to only those under enforcePaths (if configured).\n */\nfunction filterByEnforcePaths(changedFiles: string[], enforcePaths: string[] | undefined): string[] {\n if (!enforcePaths || enforcePaths.length === 0) {\n return changedFiles;\n }\n return changedFiles.filter((file) =>\n enforcePaths.some((prefix) => file.startsWith(prefix))\n );\n}\n\n/**\n * Filter to only relevant Angular files (*.routes.ts and *.component.ts).\n */\nfunction filterRelevantFiles(changedFiles: string[]): string[] {\n return changedFiles.filter((file) =>\n file.endsWith('.routes.ts') || file.endsWith('.component.ts')\n );\n}\n\nasync function runValidatorImpl(\n options: AngularNoDirectApiInResolverConfig,\n workspaceRoot: string\n): Promise<ExecutorResult> {\n const mode: DirectApiResolverMode = resolveMode(options.mode ?? 'OFF', options.ignoreModifiedUntilEpoch, options.ignoreRuleWhileOnBranch);\n const disableAllowed = options.disableAllowed ?? true;\n\n if (mode === 'OFF') {\n console.log('\\n\\u23ed\\ufe0f Skipping no-direct-api-resolver validation (mode: OFF)');\n console.log('');\n return { success: true };\n }\n\n console.log('\\n\\ud83d\\udccf Validating No Direct API in Resolver\\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\\u23ed\\ufe0f Skipping no-direct-api-resolver 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 allChangedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);\n const scopedFiles = filterByEnforcePaths(allChangedFiles, options.enforcePaths);\n const changedFiles = filterRelevantFiles(scopedFiles);\n\n if (changedFiles.length === 0) {\n console.log('\\u2705 No relevant Angular files changed (*.routes.ts, *.component.ts)');\n return { success: true };\n }\n\n console.log(`\\ud83d\\udcc2 Checking ${changedFiles.length} changed file(s)...`);\n\n let violations: Violation[] = [];\n\n if (mode === 'MODIFIED_CODE') {\n violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head, disableAllowed);\n } else if (mode === 'NEW_AND_MODIFIED_METHODS') {\n violations = findViolationsForModifiedMethods(workspaceRoot, changedFiles, base, head, disableAllowed);\n } else if (mode === 'MODIFIED_FILES') {\n violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed);\n }\n\n if (violations.length === 0) {\n console.log('\\u2705 No direct API resolver patterns found');\n return { success: true };\n }\n\n reportViolations(violations, mode, disableAllowed);\n\n return { success: false };\n}\n\nexport class NoDirectApiResolverValidator extends CodeValidator<AngularNoDirectApiInResolverConfig> {\n constructor(config: AngularNoDirectApiInResolverConfig) {\n super(config, 'angular-no-direct-api-in-resolver');\n }\n\n async run(workspaceRoot: string): Promise<ExecutorResult> {\n return runValidatorImpl(this.config, workspaceRoot);\n }\n}\n"]}
1
+ {"version":3,"file":"validate-no-direct-api-resolver.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/validate-no-direct-api-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate No Direct API in Resolver Executor\n *\n * Validates two Angular anti-patterns using LINE-BASED detection:\n *\n * ============================================================================\n * VIOLATIONS (BAD) - These patterns are flagged:\n * ============================================================================\n *\n * 1. In *.routes.ts files: inject(XxxApi) — resolvers should inject services, not APIs directly\n * 2. In *.component.ts files: this.<field>.snapshot.data — components should subscribe to\n * service BehaviorSubjects, not read route snapshot data\n *\n * ============================================================================\n * CORRECT PATTERNS (GOOD)\n * ============================================================================\n *\n * 1. In resolvers: inject(XxxService) which calls the API internally\n * 2. In components: this.myService.someObservable$ (subscribe to service BehaviorSubjects)\n *\n * ============================================================================\n * MODES (LINE-BASED)\n * ============================================================================\n * - OFF: Skip validation entirely\n * - MODIFIED_CODE: Flag violations on changed lines (lines in diff hunks)\n * - NEW_AND_MODIFIED_METHODS: Flag violations in new/modified method/route scopes\n * - NEW_AND_MODIFIED_FILES: Flag ALL violations in files that were modified\n *\n * ============================================================================\n * ESCAPE HATCH\n * ============================================================================\n * Add comment above the violation:\n * // webpieces-disable no-direct-api-resolver -- [your justification]\n * const myApi = inject(MyApi);\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as ts from 'typescript';\nimport { hasDisable, RULE_NAMES, AngularNoDirectApiInResolverConfig, DirectApiResolverMode, detectBase, getChangedFiles, getFileDiff, getChangedLineNumbers, findNewMethodSignaturesInDiff } from '@webpieces/rules-config';\nimport { CodeValidator, ExecutorResult } from './code-validator';\nimport { shouldSkipRule } from './resolve-mode';\n\ninterface Violation {\n file: string;\n line: number;\n column: number;\n context: string;\n}\n\ninterface ViolationInfo {\n line: number;\n column: number;\n context: string;\n hasDisableComment: boolean;\n}\n\n/**\n * Check if a line contains a webpieces-disable comment for no-direct-api-resolver.\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 (hasDisable(line, RULE_NAMES.NO_DIRECT_API_RESOLVER)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Find inject(XxxApi) calls in *.routes.ts files.\n * Flags any CallExpression where callee is `inject` and the first argument is an identifier ending with `Api`.\n */\nfunction findDirectApiInjections(filePath: string, workspaceRoot: string, disableAllowed: boolean): ViolationInfo[] {\n if (!filePath.endsWith('.routes.ts')) return [];\n\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: ViolationInfo[] = [];\n\n function visit(node: ts.Node): void {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n if (ts.isCallExpression(node)) {\n const callee = node.expression;\n if (ts.isIdentifier(callee) && callee.text === 'inject') {\n const firstArg = node.arguments[0];\n if (firstArg && ts.isIdentifier(firstArg) && firstArg.text.endsWith('Api')) {\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 disabled = hasDisableComment(fileLines, line);\n\n if (!disableAllowed && disabled) {\n violations.push({ line, column, context: `inject(${firstArg.text}) in route resolver`, hasDisableComment: false });\n } else {\n violations.push({ line, column, context: `inject(${firstArg.text}) in route resolver`, hasDisableComment: disabled });\n }\n }\n }\n }\n }\n } catch (err: unknown) {\n //const error = toError(err);\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 * Find this.<field>.snapshot.data access patterns in *.component.ts files.\n * Flags PropertyAccessExpression chains: this.<anything>.snapshot.data\n */\nfunction findSnapshotDataAccess(filePath: string, workspaceRoot: string, disableAllowed: boolean): ViolationInfo[] {\n if (!filePath.endsWith('.component.ts')) return [];\n\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: ViolationInfo[] = [];\n\n function visit(node: ts.Node): void {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n // Looking for: this.<field>.snapshot.data\n // AST shape: PropertyAccessExpression(.data) -> PropertyAccessExpression(.snapshot) -> PropertyAccessExpression(.<field>) -> this\n if (ts.isPropertyAccessExpression(node) && node.name.text === 'data') {\n const snapshotAccess = node.expression;\n if (ts.isPropertyAccessExpression(snapshotAccess) && snapshotAccess.name.text === 'snapshot') {\n const fieldAccess = snapshotAccess.expression;\n if (ts.isPropertyAccessExpression(fieldAccess)) {\n const receiver = fieldAccess.expression;\n if (receiver.kind === ts.SyntaxKind.ThisKeyword) {\n const fieldName = fieldAccess.name.text;\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 disabled = hasDisableComment(fileLines, line);\n\n if (!disableAllowed && disabled) {\n violations.push({ line, column, context: `this.${fieldName}.snapshot.data in component`, hasDisableComment: false });\n } else {\n violations.push({ line, column, context: `this.${fieldName}.snapshot.data in component`, hasDisableComment: disabled });\n }\n }\n }\n }\n }\n }\n } catch (err: unknown) {\n //const error = toError(err);\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 * Find all violations in a file (both inject(Api) and snapshot.data patterns).\n */\nfunction findViolationsInFile(filePath: string, workspaceRoot: string, disableAllowed: boolean): ViolationInfo[] {\n const apiViolations = findDirectApiInjections(filePath, workspaceRoot, disableAllowed);\n const snapshotViolations = findSnapshotDataAccess(filePath, workspaceRoot, disableAllowed);\n return [...apiViolations, ...snapshotViolations];\n}\n\n/**\n * MODIFIED_CODE mode: Flag violations on changed lines in diff hunks.\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 | undefined,\n disableAllowed: boolean\n): Violation[] {\n const violations: Violation[] = [];\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 = findViolationsInFile(file, workspaceRoot, disableAllowed);\n\n for (const v of allViolations) {\n if (disableAllowed && 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 context: v.context,\n });\n }\n }\n\n return violations;\n}\n\n/**\n * NEW_AND_MODIFIED_FILES mode: Flag ALL violations in files that were modified.\n */\nfunction findViolationsForModifiedFiles(workspaceRoot: string, changedFiles: string[], disableAllowed: boolean): Violation[] {\n const violations: Violation[] = [];\n\n for (const file of changedFiles) {\n const allViolations = findViolationsInFile(file, workspaceRoot, disableAllowed);\n\n for (const v of allViolations) {\n if (disableAllowed && v.hasDisableComment) continue;\n\n violations.push({\n file,\n line: v.line,\n column: v.column,\n context: v.context,\n });\n }\n }\n\n return violations;\n}\n\ninterface RangeInfo {\n name: string;\n startLine: number;\n endLine: number;\n}\n\n/**\n * Find route object ranges in *.routes.ts files.\n * A route object is an ObjectLiteralExpression that contains (directly or in descendants)\n * a `resolve` property. Returns the line range of each such top-level route object.\n */\nfunction findRouteObjectRanges(filePath: string, workspaceRoot: string): RangeInfo[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n const ranges: RangeInfo[] = [];\n\n function hasResolveProperty(node: ts.Node): boolean {\n if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && node.name.text === 'resolve') {\n return true;\n }\n let found = false;\n ts.forEachChild(node, (child) => {\n if (hasResolveProperty(child)) {\n found = true;\n }\n });\n return found;\n }\n\n function visitTopLevel(node: ts.Node): void {\n if (ts.isObjectLiteralExpression(node) && hasResolveProperty(node)) {\n const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n ranges.push({\n name: `route@${start.line + 1}`,\n startLine: start.line + 1,\n endLine: end.line + 1,\n });\n return;\n }\n ts.forEachChild(node, visitTopLevel);\n }\n\n visitTopLevel(sourceFile);\n return ranges;\n}\n\n/**\n * Find method/function ranges in *.component.ts files.\n * Returns ranges for class methods, function declarations, and arrow functions in variable declarations.\n */\nfunction findMethodRanges(filePath: string, workspaceRoot: string): RangeInfo[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n const ranges: RangeInfo[] = [];\n\n function visit(node: ts.Node): void {\n let methodName: string | undefined;\n let startLine: number | undefined;\n let endLine: number | undefined;\n\n if (ts.isMethodDeclaration(node) && node.name) {\n methodName = node.name.getText(sourceFile);\n const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n startLine = start.line + 1;\n endLine = end.line + 1;\n } else if (ts.isFunctionDeclaration(node) && node.name) {\n methodName = node.name.getText(sourceFile);\n const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n startLine = start.line + 1;\n endLine = end.line + 1;\n } else if (ts.isArrowFunction(node)) {\n if (ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {\n methodName = node.parent.name.getText(sourceFile);\n const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n startLine = start.line + 1;\n endLine = end.line + 1;\n }\n }\n\n if (methodName && startLine !== undefined && endLine !== undefined) {\n ranges.push({ name: methodName, startLine, endLine });\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return ranges;\n}\n\n/**\n * NEW_AND_MODIFIED_METHODS mode: Flag violations in new/modified method/route scopes.\n * - For *.routes.ts: If any line in a route object is changed, flag all inject(XxxApi) violations in that route\n * - For *.component.ts: If a method is new/modified, flag all snapshot.data violations in that method\n */\n// webpieces-disable max-lines-new-methods -- Method-scoped validation with route objects and component methods\nfunction findViolationsForModifiedMethods(\n workspaceRoot: string,\n changedFiles: string[],\n base: string,\n head: string | undefined,\n disableAllowed: boolean\n): Violation[] {\n const violations: Violation[] = [];\n\n for (const file of changedFiles) {\n const diff = getFileDiff(workspaceRoot, file, base, head);\n const changedLines = getChangedLineNumbers(diff);\n const newMethodNames = findNewMethodSignaturesInDiff(diff);\n\n if (changedLines.size === 0 && newMethodNames.size === 0) continue;\n\n if (file.endsWith('.routes.ts')) {\n const routeRanges = findRouteObjectRanges(file, workspaceRoot);\n const allViolations = findDirectApiInjections(file, workspaceRoot, disableAllowed);\n\n for (const range of routeRanges) {\n let rangeHasChanges = false;\n for (let line = range.startLine; line <= range.endLine; line++) {\n if (changedLines.has(line)) {\n rangeHasChanges = true;\n break;\n }\n }\n if (!rangeHasChanges) continue;\n\n for (const v of allViolations) {\n if (disableAllowed && v.hasDisableComment) continue;\n if (v.line >= range.startLine && v.line <= range.endLine) {\n violations.push({\n file,\n line: v.line,\n column: v.column,\n context: v.context,\n });\n }\n }\n }\n } else if (file.endsWith('.component.ts')) {\n const methodRanges = findMethodRanges(file, workspaceRoot);\n const allViolations = findSnapshotDataAccess(file, workspaceRoot, disableAllowed);\n\n for (const range of methodRanges) {\n const isNewMethod = newMethodNames.has(range.name);\n let rangeHasChanges = false;\n if (!isNewMethod) {\n for (let line = range.startLine; line <= range.endLine; line++) {\n if (changedLines.has(line)) {\n rangeHasChanges = true;\n break;\n }\n }\n }\n if (!isNewMethod && !rangeHasChanges) continue;\n\n for (const v of allViolations) {\n if (disableAllowed && v.hasDisableComment) continue;\n if (v.line >= range.startLine && v.line <= range.endLine) {\n violations.push({\n file,\n line: v.line,\n column: v.column,\n context: v.context,\n });\n }\n }\n }\n }\n }\n\n return violations;\n}\n\n/**\n * Report violations to console.\n */\n// webpieces-disable max-lines-new-methods -- Console output with examples and escape hatch information\nfunction reportViolations(violations: Violation[], mode: DirectApiResolverMode, disableAllowed: boolean): void {\n console.error('');\n console.error('\\u274c Direct API usage in resolvers or snapshot.data in components found!');\n console.error('');\n console.error('\\ud83d\\udcda Resolvers should use services, and components should subscribe to service observables:');\n console.error('');\n console.error(' BAD (in *.routes.ts resolver):');\n console.error(' const myApi = inject(MyApi);');\n console.error(' resolve: () => inject(MyApi).fetchData()');\n console.error('');\n console.error(' GOOD (in *.routes.ts resolver):');\n console.error(' const myService = inject(MyService);');\n console.error(' resolve: () => inject(MyService).loadData()');\n console.error('');\n console.error(' BAD (in *.component.ts):');\n console.error(' const data = this.route.snapshot.data;');\n console.error('');\n console.error(' GOOD (in *.component.ts):');\n console.error(' this.myService.data$.subscribe(data => ...)');\n console.error('');\n\n for (const v of violations) {\n console.error(` \\u274c ${v.file}:${v.line}:${v.column}`);\n console.error(` ${v.context}`);\n }\n console.error('');\n\n if (disableAllowed) {\n console.error(' Escape hatch (use sparingly):');\n console.error(' // webpieces-disable no-direct-api-resolver -- [your reason]');\n } else {\n console.error(' Escape hatch: DISABLED (disableAllowed: false)');\n console.error(' Disable comments are ignored. Fix the pattern directly.');\n }\n console.error('');\n console.error(` Current mode: ${mode}`);\n console.error('');\n}\n\n/**\n * Resolve mode considering ignoreModifiedUntilEpoch override.\n * When active, downgrades to OFF. When expired, logs a warning.\n */\nfunction resolveMode(normalMode: DirectApiResolverMode, epoch: number | undefined, branchPattern: string | undefined): DirectApiResolverMode {\n if (normalMode === 'OFF') {\n return normalMode;\n }\n const skip = shouldSkipRule(epoch, branchPattern);\n if (skip.skip) {\n console.log(`\\n\\u23ed\\ufe0f Skipping no-direct-api-resolver validation (${skip.reason})`);\n console.log('');\n return 'OFF';\n }\n return normalMode;\n}\n\n/**\n * Filter changed files to only those under enforcePaths (if configured).\n */\nfunction filterByEnforcePaths(changedFiles: string[], enforcePaths: string[] | undefined): string[] {\n if (!enforcePaths || enforcePaths.length === 0) {\n return changedFiles;\n }\n return changedFiles.filter((file) =>\n enforcePaths.some((prefix) => file.startsWith(prefix))\n );\n}\n\n/**\n * Filter to only relevant Angular files (*.routes.ts and *.component.ts).\n */\nfunction filterRelevantFiles(changedFiles: string[]): string[] {\n return changedFiles.filter((file) =>\n file.endsWith('.routes.ts') || file.endsWith('.component.ts')\n );\n}\n\nasync function runValidatorImpl(\n options: AngularNoDirectApiInResolverConfig,\n workspaceRoot: string\n): Promise<ExecutorResult> {\n const mode: DirectApiResolverMode = resolveMode(options.mode ?? 'OFF', options.ignoreModifiedUntilEpoch, options.ignoreRuleWhileOnBranch);\n const disableAllowed = options.disableAllowed ?? true;\n\n if (mode === 'OFF') {\n console.log('\\n\\u23ed\\ufe0f Skipping no-direct-api-resolver validation (mode: OFF)');\n console.log('');\n return { success: true };\n }\n\n console.log('\\n\\ud83d\\udccf Validating No Direct API in Resolver\\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\\u23ed\\ufe0f Skipping no-direct-api-resolver 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 allChangedFiles = getChangedFiles(workspaceRoot, base, head);\n const scopedFiles = filterByEnforcePaths(allChangedFiles, options.enforcePaths);\n const changedFiles = filterRelevantFiles(scopedFiles);\n\n if (changedFiles.length === 0) {\n console.log('\\u2705 No relevant Angular files changed (*.routes.ts, *.component.ts)');\n return { success: true };\n }\n\n console.log(`\\ud83d\\udcc2 Checking ${changedFiles.length} changed file(s)...`);\n\n let violations: Violation[] = [];\n\n if (mode === 'MODIFIED_CODE') {\n violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head, disableAllowed);\n } else if (mode === 'NEW_AND_MODIFIED_METHODS') {\n violations = findViolationsForModifiedMethods(workspaceRoot, changedFiles, base, head, disableAllowed);\n } else if (mode === 'NEW_AND_MODIFIED_FILES') {\n violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed);\n }\n\n if (violations.length === 0) {\n console.log('\\u2705 No direct API resolver patterns found');\n return { success: true };\n }\n\n reportViolations(violations, mode, disableAllowed);\n\n return { success: false };\n}\n\nexport class NoDirectApiResolverValidator extends CodeValidator<AngularNoDirectApiInResolverConfig> {\n constructor(config: AngularNoDirectApiInResolverConfig) {\n super(config, 'angular-no-direct-api-in-resolver');\n }\n\n async run(workspaceRoot: string): Promise<ExecutorResult> {\n return runValidatorImpl(this.config, workspaceRoot);\n }\n}\n"]}
@@ -16,7 +16,7 @@
16
16
  * ============================================================================
17
17
  * - OFF: Skip validation entirely.
18
18
  * - MODIFIED_CODE: Flag implicit-any on changed lines (lines in diff hunks).
19
- * - MODIFIED_FILES: Flag ALL implicit-any in files that were modified.
19
+ * - NEW_AND_MODIFIED_FILES: Flag ALL implicit-any in files that were modified.
20
20
  *
21
21
  * ============================================================================
22
22
  * ESCAPE HATCH
@@ -17,7 +17,7 @@
17
17
  * ============================================================================
18
18
  * - OFF: Skip validation entirely.
19
19
  * - MODIFIED_CODE: Flag implicit-any on changed lines (lines in diff hunks).
20
- * - MODIFIED_FILES: Flag ALL implicit-any in files that were modified.
20
+ * - NEW_AND_MODIFIED_FILES: Flag ALL implicit-any in files that were modified.
21
21
  *
22
22
  * ============================================================================
23
23
  * ESCAPE HATCH
@@ -28,7 +28,6 @@
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.NoImplicitAnyValidator = void 0;
30
30
  const tslib_1 = require("tslib");
31
- const child_process_1 = require("child_process");
32
31
  const fs = tslib_1.__importStar(require("fs"));
33
32
  const path = tslib_1.__importStar(require("path"));
34
33
  const ts = tslib_1.__importStar(require("typescript"));
@@ -41,76 +40,6 @@ const resolve_mode_1 = require("./resolve-mode");
41
40
  const IMPLICIT_ANY_CODES = new Set([
42
41
  7005, 7006, 7008, 7015, 7018, 7019, 7031, 7034, 7053,
43
42
  ]);
44
- function listUntrackedOrEmpty(workspaceRoot) {
45
- // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
46
- try {
47
- const output = (0, child_process_1.execSync)(`git ls-files --others --exclude-standard '*.ts' '*.tsx'`, {
48
- cwd: workspaceRoot,
49
- encoding: 'utf-8',
50
- });
51
- return output.trim().split('\n').filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
52
- }
53
- catch (err) {
54
- //const error = toError(err);
55
- return [];
56
- }
57
- }
58
- function getChangedTypeScriptFiles(workspaceRoot, base, head) {
59
- const diffTarget = head ? `${base} ${head}` : base;
60
- const output = (0, child_process_1.execSync)(`git diff --name-only ${diffTarget} -- '*.ts' '*.tsx'`, {
61
- cwd: workspaceRoot,
62
- encoding: 'utf-8',
63
- });
64
- const changed = output.trim().split('\n').filter((f) => f && !f.includes('.spec.ts') && !f.includes('.test.ts'));
65
- if (head)
66
- return changed;
67
- return Array.from(new Set([...changed, ...listUntrackedOrEmpty(workspaceRoot)]));
68
- }
69
- function getFileDiff(workspaceRoot, file, base, head) {
70
- const diffTarget = head ? `${base} ${head}` : base;
71
- const diff = (0, child_process_1.execSync)(`git diff ${diffTarget} -- "${file}"`, {
72
- cwd: workspaceRoot,
73
- encoding: 'utf-8',
74
- });
75
- if (diff || head)
76
- return diff;
77
- const fullPath = path.join(workspaceRoot, file);
78
- if (!fs.existsSync(fullPath))
79
- return '';
80
- const isUntracked = (0, child_process_1.execSync)(`git ls-files --others --exclude-standard "${file}"`, {
81
- cwd: workspaceRoot,
82
- encoding: 'utf-8',
83
- }).trim();
84
- if (!isUntracked)
85
- return '';
86
- const content = fs.readFileSync(fullPath, 'utf-8');
87
- const lines = content.split('\n');
88
- const hunk = `@@ -0,0 +1,${String(lines.length)} @@`;
89
- return hunk + '\n' + lines.map((line) => `+${line}`).join('\n');
90
- }
91
- function getChangedLineNumbers(diffContent) {
92
- const changedLines = new Set();
93
- const lines = diffContent.split('\n');
94
- let currentLine = 0;
95
- for (const line of lines) {
96
- const hunkMatch = line.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
97
- if (hunkMatch) {
98
- currentLine = parseInt(hunkMatch[1], 10);
99
- continue;
100
- }
101
- if (line.startsWith('+') && !line.startsWith('+++')) {
102
- changedLines.add(currentLine);
103
- currentLine++;
104
- }
105
- else if (line.startsWith('-') && !line.startsWith('---')) {
106
- // Deletions don't increment line number
107
- }
108
- else {
109
- currentLine++;
110
- }
111
- }
112
- return changedLines;
113
- }
114
43
  function hasDisableComment(lines, lineNumber) {
115
44
  const startCheck = Math.max(0, lineNumber - 5);
116
45
  for (let i = lineNumber - 2; i >= startCheck; i--) {
@@ -200,8 +129,8 @@ function findImplicitAnyInFile(filePath, workspaceRoot) {
200
129
  function findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head, disableAllowed) {
201
130
  const results = [];
202
131
  for (const file of changedFiles) {
203
- const diff = getFileDiff(workspaceRoot, file, base, head);
204
- const changedLines = getChangedLineNumbers(diff);
132
+ const diff = (0, rules_config_1.getFileDiff)(workspaceRoot, file, base, head);
133
+ const changedLines = (0, rules_config_1.getChangedLineNumbers)(diff);
205
134
  if (changedLines.size === 0)
206
135
  continue;
207
136
  const all = findImplicitAnyInFile(file, workspaceRoot);
@@ -227,23 +156,6 @@ function findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllo
227
156
  }
228
157
  return results;
229
158
  }
230
- function detectBase(workspaceRoot) {
231
- for (const ref of ['origin/main', 'main']) {
232
- // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
233
- try {
234
- const merged = (0, child_process_1.execSync)(`git merge-base HEAD ${ref}`, {
235
- cwd: workspaceRoot, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'],
236
- }).trim();
237
- if (merged)
238
- return merged;
239
- }
240
- catch (err) {
241
- //const error = toError(err);
242
- // try next ref
243
- }
244
- }
245
- return null;
246
- }
247
159
  function reportViolations(violations, mode) {
248
160
  console.error('');
249
161
  console.error('\u274c Implicit-any inferences found! Add explicit type annotations.');
@@ -289,7 +201,7 @@ async function runInternal(options, workspaceRoot) {
289
201
  let base = process.env['NX_BASE'];
290
202
  const head = process.env['NX_HEAD'];
291
203
  if (!base) {
292
- base = detectBase(workspaceRoot) ?? undefined;
204
+ base = (0, rules_config_1.detectBase)(workspaceRoot) ?? undefined;
293
205
  if (!base) {
294
206
  console.log('\n\u23ed\ufe0f Skipping no-implicit-any validation (could not detect base branch)');
295
207
  console.log('');
@@ -299,7 +211,7 @@ async function runInternal(options, workspaceRoot) {
299
211
  console.log(` Base: ${base}`);
300
212
  console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
301
213
  console.log('');
302
- const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
214
+ const changedFiles = (0, rules_config_1.getChangedFiles)(workspaceRoot, base, head);
303
215
  if (changedFiles.length === 0) {
304
216
  console.log('\u2705 No TypeScript files changed');
305
217
  return { success: true };
@@ -309,7 +221,7 @@ async function runInternal(options, workspaceRoot) {
309
221
  if (mode === 'MODIFIED_CODE') {
310
222
  violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head, disableAllowed);
311
223
  }
312
- else if (mode === 'MODIFIED_FILES') {
224
+ else if (mode === 'NEW_AND_MODIFIED_FILES') {
313
225
  violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed);
314
226
  }
315
227
  if (violations.length === 0) {