@webpieces/code-rules 0.4.490 → 0.4.492
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.
- package/package.json +2 -2
- package/src/tag-rule.d.ts +2 -2
- package/src/tag-rule.js +1 -1
- package/src/tag-rule.js.map +1 -1
- package/src/validate-catch-error-pattern.js +2 -2
- package/src/validate-catch-error-pattern.js.map +1 -1
- package/src/validate-dtos.js +2 -2
- package/src/validate-dtos.js.map +1 -1
- package/src/validate-inject-annotation-not-needed-for-concrete-class.js +1 -1
- package/src/validate-inject-annotation-not-needed-for-concrete-class.js.map +1 -1
- package/src/validate-match-rules.js +2 -2
- package/src/validate-match-rules.js.map +1 -1
- package/src/validate-modified-files.js +3 -3
- package/src/validate-modified-files.js.map +1 -1
- package/src/validate-modified-methods.js +3 -3
- package/src/validate-modified-methods.js.map +1 -1
- package/src/validate-new-methods.js +1 -1
- package/src/validate-new-methods.js.map +1 -1
- package/src/validate-no-any-unknown.js +2 -2
- package/src/validate-no-any-unknown.js.map +1 -1
- package/src/validate-no-client-creation-outside-server-or-client.js +1 -1
- package/src/validate-no-client-creation-outside-server-or-client.js.map +1 -1
- package/src/validate-no-custom-css.js +1 -1
- package/src/validate-no-custom-css.js.map +1 -1
- package/src/validate-no-destructure.js +2 -2
- package/src/validate-no-destructure.js.map +1 -1
- package/src/validate-no-direct-api-resolver.js +2 -2
- package/src/validate-no-direct-api-resolver.js.map +1 -1
- package/src/validate-no-function-outside-class.js +1 -1
- package/src/validate-no-function-outside-class.js.map +1 -1
- package/src/validate-no-implicit-any.js +1 -1
- package/src/validate-no-implicit-any.js.map +1 -1
- package/src/validate-no-inline-types.js +2 -2
- package/src/validate-no-inline-types.js.map +1 -1
- package/src/validate-no-process-exit-outside-main.js +1 -1
- package/src/validate-no-process-exit-outside-main.js.map +1 -1
- package/src/validate-no-symbol-di-tokens.js +1 -1
- package/src/validate-no-symbol-di-tokens.js.map +1 -1
- package/src/validate-no-unmanaged-exceptions.js +2 -2
- package/src/validate-no-unmanaged-exceptions.js.map +1 -1
- package/src/validate-prisma-converters.js +2 -2
- package/src/validate-prisma-converters.js.map +1 -1
- package/src/validate-return-types.js +2 -2
- package/src/validate-return-types.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-no-destructure.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/validate-no-destructure.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate No Destructure Executor\n *\n * Validates that destructuring patterns are not used in TypeScript code.\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, y } = obj — object destructuring in variable declarations\n * - const [a, b] = fn() — array destructuring (except Promise.all)\n * - for (const { email } of items) — object destructuring in for-of loops\n * - for (const [a, b] of items) — array destructuring in for-of (except Object.entries)\n * - const { page = 0 } = opts — destructuring with defaults\n * - const { done: streamDone } = obj — destructuring with renaming\n * - function foo({ x, y }: Type) — function parameter destructuring\n *\n * ============================================================================\n * ALLOWED (skip — NOT violations)\n * ============================================================================\n *\n * - const [a, b] = await Promise.all([...]) — Promise.all array destructuring\n * - for (const [key, value] of Object.entries(obj)) — Object.entries in for-of\n * - const { extracted, ...rest } = obj — rest operator separation\n * - Lines with // webpieces-disable no-destructure -- [reason] (only when disableAllowed: true)\n * - Files under a configured `allowedPaths` glob (shared isPathExcluded glob/prefix/segment\n * semantics) — e.g. a React/React Native tree, where useState and destructured props are the\n * framework's own idiom. This is the ONLY escape when disableAllowed: false.\n *\n * ============================================================================\n * MODES (LINE-BASED)\n * ============================================================================\n * - OFF: Skip validation entirely\n * - NEW_AND_MODIFIED_CODE: Flag destructuring on changed lines (lines in diff hunks)\n * - NEW_AND_MODIFIED_FILES: Flag ALL destructuring in files that were modified\n *\n * ============================================================================\n * ESCAPE HATCH\n * ============================================================================\n * Add comment above the violation:\n * // webpieces-disable no-destructure -- [your justification]\n * const { x, y } = obj;\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as ts from 'typescript';\nimport { hasDisable, RULE_NAMES, NoDestructureConfig, ModifiedCodeMode, detectBase, getChangedFiles, getFileDiff, getChangedLineNumbers, isPathExcluded } from '@webpieces/rules-config';\nimport { CodeValidator, ExecutorResult } from './code-validator';\nimport { injectable, bindingScopeValues } from 'inversify';\nimport { shouldSkipRule } from './resolve-mode';\n\ninterface DestructureViolation {\n file: string;\n line: number;\n column: number;\n context: string;\n}\n\n/**\n * Check if a line contains a webpieces-disable comment for no-destructure.\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_DESTRUCTURE)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if an ArrayBindingPattern's initializer is `await Promise.all(...)`.\n */\nfunction isPromiseAllDestructure(node: ts.ArrayBindingPattern): boolean {\n const parent = node.parent;\n if (!ts.isVariableDeclaration(parent)) return false;\n const initializer = parent.initializer;\n if (!initializer) return false;\n\n // Handle: const [a, b] = await Promise.all([...])\n if (ts.isAwaitExpression(initializer)) {\n const awaitedExpr = initializer.expression;\n if (ts.isCallExpression(awaitedExpr)) {\n const callExpr = awaitedExpr.expression;\n // Promise.all(...)\n if (ts.isPropertyAccessExpression(callExpr) && callExpr.name.text === 'all') {\n const obj = callExpr.expression;\n if (ts.isIdentifier(obj) && obj.text === 'Promise') {\n return true;\n }\n }\n }\n }\n\n return false;\n}\n\n/**\n * Check if an ArrayBindingPattern in a for-of loop iterates over Object.entries(...).\n */\nfunction isObjectEntriesForOf(node: ts.ArrayBindingPattern): boolean {\n // Walk up: ArrayBindingPattern -> VariableDeclaration -> VariableDeclarationList -> ForOfStatement\n const varDecl = node.parent;\n if (!ts.isVariableDeclaration(varDecl)) return false;\n\n const varDeclList = varDecl.parent;\n if (!ts.isVariableDeclarationList(varDeclList)) return false;\n\n const forOfStmt = varDeclList.parent;\n if (!ts.isForOfStatement(forOfStmt)) return false;\n\n // Check iterable expression ends with .entries()\n const iterable = forOfStmt.expression;\n if (ts.isCallExpression(iterable)) {\n const callExpr = iterable.expression;\n if (ts.isPropertyAccessExpression(callExpr) && callExpr.name.text === 'entries') {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if an ObjectBindingPattern contains a rest element (...rest).\n */\nfunction hasRestElement(node: ts.ObjectBindingPattern): boolean {\n for (const element of node.elements) {\n if (element.dotDotDotToken) {\n return true;\n }\n }\n return false;\n}\n\nexport interface DestructureInfo {\n line: number;\n column: number;\n context: string;\n hasDisableComment: boolean;\n}\n\n/**\n * Find all destructuring patterns in a file using AST.\n */\n// webpieces-disable max-lines-new-methods -- AST traversal with multiple destructuring pattern checks and exception detection\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nexport function findDestructuringInFile(filePath: string, workspaceRoot: string, disableAllowed: boolean, allowedPaths: string[]): DestructureInfo[] {\n // Guard on the REPO-RELATIVE path, before the join below — globs like `mobile/**` never match an\n // absolute path. This is the only escape when disableAllowed is false.\n if (isPathExcluded(filePath, allowedPaths)) return [];\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: DestructureInfo[] = [];\n\n // webpieces-disable max-lines-new-methods -- AST visitor needs to handle object/array binding patterns in declarations, for-of, and parameters\n function visit(node: ts.Node): void {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n // Check ObjectBindingPattern\n if (ts.isObjectBindingPattern(node)) {\n // Exception: rest operator separation\n if (hasRestElement(node)) {\n ts.forEachChild(node, visit);\n return;\n }\n\n const context = getDestructureContext(node);\n recordViolation(node, context, fileLines, sourceFile, violations, disableAllowed);\n }\n\n // Check ArrayBindingPattern\n if (ts.isArrayBindingPattern(node)) {\n // Exception: Promise.all destructure\n if (isPromiseAllDestructure(node)) {\n ts.forEachChild(node, visit);\n return;\n }\n\n // Exception: Object.entries in for-of\n if (isObjectEntriesForOf(node)) {\n ts.forEachChild(node, visit);\n return;\n }\n\n const context = getDestructureContext(node);\n recordViolation(node, context, fileLines, sourceFile, violations, disableAllowed);\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\nfunction recordViolation(\n node: ts.Node,\n context: string,\n fileLines: string[],\n sourceFile: ts.SourceFile,\n violations: DestructureInfo[],\n disableAllowed: boolean,\n): void {\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 // When disableAllowed is false, ignore disable comments — still a violation\n violations.push({ line, column, context, hasDisableComment: false });\n } else {\n violations.push({ line, column, context, hasDisableComment: disabled });\n }\n }\n}\n\n/**\n * Get a description of where the destructuring pattern appears.\n */\nfunction getDestructureContext(node: ts.Node): string {\n const parent = node.parent;\n if (ts.isParameter(parent)) {\n return 'function parameter destructuring';\n }\n if (ts.isVariableDeclaration(parent)) {\n const grandparent = parent.parent;\n if (grandparent && ts.isVariableDeclarationList(grandparent)) {\n const forOfParent = grandparent.parent;\n if (forOfParent && ts.isForOfStatement(forOfParent)) {\n return ts.isObjectBindingPattern(node)\n ? 'object destructuring in for-of loop'\n : 'array destructuring in for-of loop';\n }\n }\n return ts.isObjectBindingPattern(node)\n ? 'object destructuring in variable declaration'\n : 'array destructuring in variable declaration';\n }\n return ts.isObjectBindingPattern(node)\n ? 'object destructuring'\n : 'array destructuring';\n}\n\n/**\n * NEW_AND_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 allowedPaths: string[]\n): DestructureViolation[] {\n const violations: DestructureViolation[] = [];\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 = findDestructuringInFile(file, workspaceRoot, disableAllowed, allowedPaths);\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 */\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nfunction findViolationsForModifiedFiles(workspaceRoot: string, changedFiles: string[], disableAllowed: boolean, allowedPaths: string[]): DestructureViolation[] {\n const violations: DestructureViolation[] = [];\n\n for (const file of changedFiles) {\n const allViolations = findDestructuringInFile(file, workspaceRoot, disableAllowed, allowedPaths);\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\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: DestructureViolation[], mode: ModifiedCodeMode, disableAllowed: boolean): void {\n console.error('');\n console.error('\\u274c Destructuring patterns found! Use explicit property access instead.');\n console.error('');\n console.error('\\ud83d\\udcda Avoiding destructuring improves code traceability:');\n console.error('');\n console.error(' BAD: const { name, age } = user;');\n console.error(' GOOD: const name = user.name;');\n console.error(' const age = user.age;');\n console.error('');\n console.error(' BAD: function process({ x, y }: Point) { }');\n console.error(' GOOD: function process(point: Point) { point.x; point.y; }');\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 console.error(' Allowed exceptions:');\n console.error(' - const [a, b] = await Promise.all([...])');\n console.error(' - for (const [key, value] of Object.entries(obj))');\n console.error(' - const { extracted, ...rest } = obj (rest operator separation)');\n console.error('');\n\n if (disableAllowed) {\n console.error(' Escape hatch (use sparingly):');\n console.error(' // webpieces-disable no-destructure -- [your reason]');\n } else {\n console.error(' Escape hatch: DISABLED (disableAllowed: false)');\n console.error(' Disable comments are ignored. Fix the destructuring directly.');\n }\n console.error(' Whole-tree exemption (e.g. React/React Native): add a glob to no-destructure.allowedPaths in webpieces.config.json');\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 resolveNoDestructureMode(normalMode: ModifiedCodeMode, epoch: number | undefined, branchPattern: string | undefined): ModifiedCodeMode {\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-destructure validation (${skip.reason})`);\n console.log('');\n return 'OFF';\n }\n return normalMode;\n}\n\nasync function runValidatorImpl(\n options: NoDestructureConfig,\n workspaceRoot: string\n): Promise<ExecutorResult> {\n const mode: ModifiedCodeMode = resolveNoDestructureMode(options.mode ?? 'OFF', options.ignoreModifiedUntilEpoch, options.ignoreRuleWhileOnBranch);\n const disableAllowed = options.disableAllowed ?? true;\n const allowedPaths = options.allowedPaths ?? [];\n\n if (mode === 'OFF') {\n console.log('\\n\\u23ed\\ufe0f Skipping no-destructure validation (mode: OFF)');\n console.log('');\n return { success: true };\n }\n\n console.log('\\n\\ud83d\\udccf Validating No Destructuring\\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-destructure 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 = getChangedFiles(workspaceRoot, base, head);\n\n if (changedFiles.length === 0) {\n console.log('\\u2705 No TypeScript files changed');\n return { success: true };\n }\n\n console.log(`\\ud83d\\udcc2 Checking ${changedFiles.length} changed file(s)...`);\n\n let violations: DestructureViolation[] = [];\n\n if (mode === 'NEW_AND_MODIFIED_CODE') {\n violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head, disableAllowed, allowedPaths);\n } else if (mode === 'NEW_AND_MODIFIED_FILES') {\n violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed, allowedPaths);\n }\n\n if (violations.length === 0) {\n console.log('\\u2705 No destructuring patterns found');\n return { success: true };\n }\n\n reportViolations(violations, mode, disableAllowed);\n\n return { success: false };\n}\n\n@injectable(bindingScopeValues.Singleton)\nexport class NoDestructureValidator extends CodeValidator<NoDestructureConfig> {\n constructor(config: NoDestructureConfig) {\n super(config, 'no-destructure');\n }\n\n async run(workspaceRoot: string): Promise<ExecutorResult> {\n return runValidatorImpl(this.config, workspaceRoot);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validate-no-destructure.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/validate-no-destructure.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate No Destructure Executor\n *\n * Validates that destructuring patterns are not used in TypeScript code.\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, y } = obj — object destructuring in variable declarations\n * - const [a, b] = fn() — array destructuring (except Promise.all)\n * - for (const { email } of items) — object destructuring in for-of loops\n * - for (const [a, b] of items) — array destructuring in for-of (except Object.entries)\n * - const { page = 0 } = opts — destructuring with defaults\n * - const { done: streamDone } = obj — destructuring with renaming\n * - function foo({ x, y }: Type) — function parameter destructuring\n *\n * ============================================================================\n * ALLOWED (skip — NOT violations)\n * ============================================================================\n *\n * - const [a, b] = await Promise.all([...]) — Promise.all array destructuring\n * - for (const [key, value] of Object.entries(obj)) — Object.entries in for-of\n * - const { extracted, ...rest } = obj — rest operator separation\n * - Lines with // webpieces-disable no-destructure -- [reason] (only when disableAllowed: true)\n * - Files under a configured `allowedPaths` glob (shared isPathExcluded glob/prefix/segment\n * semantics) — e.g. a React/React Native tree, where useState and destructured props are the\n * framework's own idiom. This is the ONLY escape when disableAllowed: false.\n *\n * ============================================================================\n * MODES (LINE-BASED)\n * ============================================================================\n * - OFF: Skip validation entirely\n * - NEW_AND_MODIFIED_CODE: Flag destructuring on changed lines (lines in diff hunks)\n * - NEW_AND_MODIFIED_FILES: Flag ALL destructuring in files that were modified\n *\n * ============================================================================\n * ESCAPE HATCH\n * ============================================================================\n * Add comment above the violation:\n * // webpieces-disable no-destructure -- [your justification]\n * const { x, y } = obj;\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as ts from 'typescript';\nimport { hasDisable, RULE_NAMES, NoDestructureConfig, ModifiedCodeMode, detectBase, getChangedFiles, getFileDiff, getChangedLineNumbers, isPathExcluded } from '@webpieces/rules-config';\nimport { CodeValidator, ExecutorResult } from './code-validator';\nimport { injectable, bindingScopeValues } from 'inversify';\nimport { shouldSkipRule } from './resolve-mode';\n\ninterface DestructureViolation {\n file: string;\n line: number;\n column: number;\n context: string;\n}\n\n/**\n * Check if a line contains a webpieces-disable comment for no-destructure.\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_DESTRUCTURE)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if an ArrayBindingPattern's initializer is `await Promise.all(...)`.\n */\nfunction isPromiseAllDestructure(node: ts.ArrayBindingPattern): boolean {\n const parent = node.parent;\n if (!ts.isVariableDeclaration(parent)) return false;\n const initializer = parent.initializer;\n if (!initializer) return false;\n\n // Handle: const [a, b] = await Promise.all([...])\n if (ts.isAwaitExpression(initializer)) {\n const awaitedExpr = initializer.expression;\n if (ts.isCallExpression(awaitedExpr)) {\n const callExpr = awaitedExpr.expression;\n // Promise.all(...)\n if (ts.isPropertyAccessExpression(callExpr) && callExpr.name.text === 'all') {\n const obj = callExpr.expression;\n if (ts.isIdentifier(obj) && obj.text === 'Promise') {\n return true;\n }\n }\n }\n }\n\n return false;\n}\n\n/**\n * Check if an ArrayBindingPattern in a for-of loop iterates over Object.entries(...).\n */\nfunction isObjectEntriesForOf(node: ts.ArrayBindingPattern): boolean {\n // Walk up: ArrayBindingPattern -> VariableDeclaration -> VariableDeclarationList -> ForOfStatement\n const varDecl = node.parent;\n if (!ts.isVariableDeclaration(varDecl)) return false;\n\n const varDeclList = varDecl.parent;\n if (!ts.isVariableDeclarationList(varDeclList)) return false;\n\n const forOfStmt = varDeclList.parent;\n if (!ts.isForOfStatement(forOfStmt)) return false;\n\n // Check iterable expression ends with .entries()\n const iterable = forOfStmt.expression;\n if (ts.isCallExpression(iterable)) {\n const callExpr = iterable.expression;\n if (ts.isPropertyAccessExpression(callExpr) && callExpr.name.text === 'entries') {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if an ObjectBindingPattern contains a rest element (...rest).\n */\nfunction hasRestElement(node: ts.ObjectBindingPattern): boolean {\n for (const element of node.elements) {\n if (element.dotDotDotToken) {\n return true;\n }\n }\n return false;\n}\n\nexport interface DestructureInfo {\n line: number;\n column: number;\n context: string;\n hasDisableComment: boolean;\n}\n\n/**\n * Find all destructuring patterns in a file using AST.\n */\n// webpieces-disable max-lines-new-methods -- AST traversal with multiple destructuring pattern checks and exception detection\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nexport function findDestructuringInFile(filePath: string, workspaceRoot: string, disableAllowed: boolean, allowedPaths: string[]): DestructureInfo[] {\n // Guard on the REPO-RELATIVE path, before the join below — globs like `mobile/**` never match an\n // absolute path. This is the only escape when disableAllowed is false.\n if (isPathExcluded(filePath, allowedPaths)) return [];\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: DestructureInfo[] = [];\n\n // webpieces-disable max-lines-new-methods -- AST visitor needs to handle object/array binding patterns in declarations, for-of, and parameters\n function visit(node: ts.Node): void {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n // Check ObjectBindingPattern\n if (ts.isObjectBindingPattern(node)) {\n // Exception: rest operator separation\n if (hasRestElement(node)) {\n ts.forEachChild(node, visit);\n return;\n }\n\n const context = getDestructureContext(node);\n recordViolation(node, context, fileLines, sourceFile, violations, disableAllowed);\n }\n\n // Check ArrayBindingPattern\n if (ts.isArrayBindingPattern(node)) {\n // Exception: Promise.all destructure\n if (isPromiseAllDestructure(node)) {\n ts.forEachChild(node, visit);\n return;\n }\n\n // Exception: Object.entries in for-of\n if (isObjectEntriesForOf(node)) {\n ts.forEachChild(node, visit);\n return;\n }\n\n const context = getDestructureContext(node);\n recordViolation(node, context, fileLines, sourceFile, violations, disableAllowed);\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\nfunction recordViolation(\n node: ts.Node,\n context: string,\n fileLines: string[],\n sourceFile: ts.SourceFile,\n violations: DestructureInfo[],\n disableAllowed: boolean,\n): void {\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 // When disableAllowed is false, ignore disable comments — still a violation\n violations.push({ line, column, context, hasDisableComment: false });\n } else {\n violations.push({ line, column, context, hasDisableComment: disabled });\n }\n }\n}\n\n/**\n * Get a description of where the destructuring pattern appears.\n */\nfunction getDestructureContext(node: ts.Node): string {\n const parent = node.parent;\n if (ts.isParameter(parent)) {\n return 'function parameter destructuring';\n }\n if (ts.isVariableDeclaration(parent)) {\n const grandparent = parent.parent;\n if (grandparent && ts.isVariableDeclarationList(grandparent)) {\n const forOfParent = grandparent.parent;\n if (forOfParent && ts.isForOfStatement(forOfParent)) {\n return ts.isObjectBindingPattern(node)\n ? 'object destructuring in for-of loop'\n : 'array destructuring in for-of loop';\n }\n }\n return ts.isObjectBindingPattern(node)\n ? 'object destructuring in variable declaration'\n : 'array destructuring in variable declaration';\n }\n return ts.isObjectBindingPattern(node)\n ? 'object destructuring'\n : 'array destructuring';\n}\n\n/**\n * NEW_AND_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 allowedPaths: string[]\n): DestructureViolation[] {\n const violations: DestructureViolation[] = [];\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 = findDestructuringInFile(file, workspaceRoot, disableAllowed, allowedPaths);\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 */\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nfunction findViolationsForModifiedFiles(workspaceRoot: string, changedFiles: string[], disableAllowed: boolean, allowedPaths: string[]): DestructureViolation[] {\n const violations: DestructureViolation[] = [];\n\n for (const file of changedFiles) {\n const allViolations = findDestructuringInFile(file, workspaceRoot, disableAllowed, allowedPaths);\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\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: DestructureViolation[], mode: ModifiedCodeMode, disableAllowed: boolean): void {\n console.error('');\n console.error('\\u274c Destructuring patterns found! Use explicit property access instead.');\n console.error('');\n console.error('\\ud83d\\udcda Avoiding destructuring improves code traceability:');\n console.error('');\n console.error(' BAD: const { name, age } = user;');\n console.error(' GOOD: const name = user.name;');\n console.error(' const age = user.age;');\n console.error('');\n console.error(' BAD: function process({ x, y }: Point) { }');\n console.error(' GOOD: function process(point: Point) { point.x; point.y; }');\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 console.error(' Allowed exceptions:');\n console.error(' - const [a, b] = await Promise.all([...])');\n console.error(' - for (const [key, value] of Object.entries(obj))');\n console.error(' - const { extracted, ...rest } = obj (rest operator separation)');\n console.error('');\n\n if (disableAllowed) {\n console.error(' Escape hatch (use sparingly):');\n console.error(' // webpieces-disable no-destructure -- [your reason]');\n } else {\n console.error(' Escape hatch: DISABLED (disableAllowed: false)');\n console.error(' Disable comments are ignored. Fix the destructuring directly.');\n }\n console.error(' Whole-tree exemption (e.g. React/React Native): add a glob to no-destructure.allowedPaths in webpieces.config.json');\n console.error('');\n console.error(` Current mode: ${mode}`);\n console.error('');\n}\n\n/**\n * Resolve mode considering turnOffRuleUntilEpoch override.\n * When active, downgrades to OFF. When expired, logs a warning.\n */\nfunction resolveNoDestructureMode(normalMode: ModifiedCodeMode, epoch: number | undefined, branchPattern: string | undefined): ModifiedCodeMode {\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-destructure validation (${skip.reason})`);\n console.log('');\n return 'OFF';\n }\n return normalMode;\n}\n\nasync function runValidatorImpl(\n options: NoDestructureConfig,\n workspaceRoot: string\n): Promise<ExecutorResult> {\n const mode: ModifiedCodeMode = resolveNoDestructureMode(options.mode ?? 'OFF', options.turnOffRuleUntilEpoch, (options.turnOffRuleWhileOnBranch ?? undefined));\n const disableAllowed = options.disableAllowed ?? true;\n const allowedPaths = options.allowedPaths ?? [];\n\n if (mode === 'OFF') {\n console.log('\\n\\u23ed\\ufe0f Skipping no-destructure validation (mode: OFF)');\n console.log('');\n return { success: true };\n }\n\n console.log('\\n\\ud83d\\udccf Validating No Destructuring\\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-destructure 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 = getChangedFiles(workspaceRoot, base, head);\n\n if (changedFiles.length === 0) {\n console.log('\\u2705 No TypeScript files changed');\n return { success: true };\n }\n\n console.log(`\\ud83d\\udcc2 Checking ${changedFiles.length} changed file(s)...`);\n\n let violations: DestructureViolation[] = [];\n\n if (mode === 'NEW_AND_MODIFIED_CODE') {\n violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head, disableAllowed, allowedPaths);\n } else if (mode === 'NEW_AND_MODIFIED_FILES') {\n violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed, allowedPaths);\n }\n\n if (violations.length === 0) {\n console.log('\\u2705 No destructuring patterns found');\n return { success: true };\n }\n\n reportViolations(violations, mode, disableAllowed);\n\n return { success: false };\n}\n\n@injectable(bindingScopeValues.Singleton)\nexport class NoDestructureValidator extends CodeValidator<NoDestructureConfig> {\n constructor(config: NoDestructureConfig) {\n super(config, 'no-destructure');\n }\n\n async run(workspaceRoot: string): Promise<ExecutorResult> {\n return runValidatorImpl(this.config, workspaceRoot);\n }\n}\n"]}
|
|
@@ -420,7 +420,7 @@ function reportViolations(violations, mode, disableAllowed) {
|
|
|
420
420
|
console.error('');
|
|
421
421
|
}
|
|
422
422
|
/**
|
|
423
|
-
* Resolve mode considering
|
|
423
|
+
* Resolve mode considering turnOffRuleUntilEpoch override.
|
|
424
424
|
* When active, downgrades to OFF. When expired, logs a warning.
|
|
425
425
|
*/
|
|
426
426
|
function resolveMode(normalMode, epoch, branchPattern) {
|
|
@@ -451,7 +451,7 @@ function filterRelevantFiles(changedFiles) {
|
|
|
451
451
|
return changedFiles.filter((file) => file.endsWith('.routes.ts') || file.endsWith('.component.ts'));
|
|
452
452
|
}
|
|
453
453
|
async function runValidatorImpl(options, workspaceRoot) {
|
|
454
|
-
const mode = resolveMode(options.mode ?? 'OFF', options.
|
|
454
|
+
const mode = resolveMode(options.mode ?? 'OFF', options.turnOffRuleUntilEpoch, (options.turnOffRuleWhileOnBranch ?? undefined));
|
|
455
455
|
const disableAllowed = options.disableAllowed ?? true;
|
|
456
456
|
if (mode === 'OFF') {
|
|
457
457
|
console.log('\n\u23ed\ufe0f Skipping no-direct-api-resolver validation (mode: OFF)');
|
|
@@ -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 * - NEW_AND_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 { injectable, bindingScopeValues } from 'inversify';\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 * NEW_AND_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 === 'NEW_AND_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\n@injectable(bindingScopeValues.Singleton)\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 * - NEW_AND_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 { injectable, bindingScopeValues } from 'inversify';\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 * NEW_AND_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 turnOffRuleUntilEpoch 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.turnOffRuleUntilEpoch, (options.turnOffRuleWhileOnBranch ?? undefined));\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 === 'NEW_AND_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\n@injectable(bindingScopeValues.Singleton)\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"]}
|
|
@@ -217,7 +217,7 @@ function resolveMode(normalMode, epoch, branchPattern) {
|
|
|
217
217
|
return normalMode;
|
|
218
218
|
}
|
|
219
219
|
async function runValidatorImpl(options, workspaceRoot) {
|
|
220
|
-
const mode = resolveMode(options.mode ?? 'OFF', options.
|
|
220
|
+
const mode = resolveMode(options.mode ?? 'OFF', options.turnOffRuleUntilEpoch, (options.turnOffRuleWhileOnBranch ?? undefined));
|
|
221
221
|
const disableAllowed = options.disableAllowed ?? true;
|
|
222
222
|
const allowedPaths = options.allowedPaths ?? [];
|
|
223
223
|
if (mode === 'OFF') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-no-function-outside-class.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/validate-no-function-outside-class.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate No Function Outside Class\n *\n * Flags a function CREATED OUTSIDE A CLASS at module scope, or a STATIC class member:\n * - a top-level `function foo()` / `export function foo()` declaration,\n * - a top-level `const foo = () => {}` / `const foo = function(){}`, and\n * - a `static foo() {}` method or `static foo = () => {}` field-function (a static member\n * belongs to the class object, not an instance, so it can't be injected either).\n *\n * WHY: webpieces DI + @DocumentDesign only work when behavior lives in injectable classes that can be\n * wired into each other. A module-scope function is a dead-end the DI graph can't reach — move the\n * logic onto a `@provideSingleton()` class and inject it instead.\n *\n * Uses the TypeScript AST so class-membership is checked precisely (not a regex heuristic): a node is a\n * violation only when its parent is the SourceFile (module scope). That automatically EXEMPTS inline\n * callbacks (`arr.map(x => x)`), promise handlers, nested functions inside methods, and functions\n * nested in other functions — their parent is a Block/CallExpression, never the SourceFile.\n *\n * ALLOWED (skip — NOT violations)\n * - Any function/arrow nested inside a class method, another function, or a callback.\n * - Non-function top-level consts: `const SCHEMA = z.object({})`, `const MAX = 5`, object/array literals.\n * - Ambient declarations (`declare function ...`) and whole `*.d.ts` files.\n * - Test files (*.test.ts, *.spec.ts, __tests__/**).\n * - Files under a configured `allowedPaths` glob (e.g. React component/hook trees that legitimately use\n * module-scope functions). Matched with the shared `isPathExcluded` glob/prefix/segment semantics.\n * - Lines with `// webpieces-disable no-function-outside-class -- <reason>` (when disableAllowed).\n *\n * MODES (AST + LINE-SCOPED)\n * - OFF: Skip.\n * - NEW_AND_MODIFIED_CODE: Flag only on changed lines (diff hunks).\n * - NEW_AND_MODIFIED_FILES: Flag every occurrence in any modified file.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as ts from 'typescript';\nimport { hasDisable, RULE_NAMES, NoFunctionOutsideClassConfig, ModifiedCodeMode, detectBase, getChangedFiles, getFileDiff, getChangedLineNumbers, isPathExcluded } from '@webpieces/rules-config';\nimport { CodeValidator, ExecutorResult } from './code-validator';\nimport { injectable, bindingScopeValues } from 'inversify';\nimport { shouldSkipRule } from './resolve-mode';\n\nconst SHARED_MESSAGE = `Functions must live inside a class as INSTANCE methods — a function created at module scope, OR a\nstatic method, can't be injected, so webpieces DI + @DocumentDesign can't wire it into anything. A\nstatic method is just a module-scope function wearing a class as a namespace.\n BAD: export function computeTotal(cart: Cart): number { ... }\n BAD: export class CartMath { static computeTotal(cart: Cart): number { ... } } // static = not injectable\n GOOD: @injectable(bindingScopeValues.Singleton)\n export class CartService { computeTotal(cart: Cart): number { ... } }\nThen inject CartService where you need it. Inline callbacks (arr.map(x => x)), promise handlers, and\nfunctions nested inside a method are fine — only MODULE-SCOPE function declarations, top-level\nconst-assigned functions, and STATIC methods/field-functions are flagged.`;\n\ninterface FnViolation {\n file: string;\n line: number;\n column: number;\n context: string;\n}\n\ninterface FnViolationInfo {\n line: number;\n column: number;\n context: string;\n hasDisableComment: boolean;\n}\n\nfunction isTestFile(filePath: string): boolean {\n return filePath.includes('.spec.ts') || filePath.includes('.test.ts') || filePath.includes('__tests__/');\n}\n\nfunction isDeclarationFile(filePath: string): boolean {\n return filePath.endsWith('.d.ts');\n}\n\n// True for a node carrying a `declare` modifier (ambient signature — not a real definition).\nfunction hasDeclareModifier(node: ts.Node): boolean {\n if (!ts.canHaveModifiers(node)) return false;\n const mods = ts.getModifiers(node);\n return mods?.some((m: ts.Modifier): boolean => m.kind === ts.SyntaxKind.DeclareKeyword) ?? false;\n}\n\n// True for a class member carrying the `static` modifier. A static method/field-function belongs\n// to the class object, not an instance, so it can't be injected — it is procedural code wearing a\n// class as a namespace, and is flagged the same as a module-scope function.\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nfunction hasStaticModifier(node: ts.Node): boolean {\n if (!ts.canHaveModifiers(node)) return false;\n const mods = ts.getModifiers(node);\n return mods?.some((m: ts.Modifier): boolean => m.kind === ts.SyntaxKind.StaticKeyword) ?? false;\n}\n\n// A `static` method, or a `static` field initialized to an arrow/function-expression, on a class.\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nfunction isStaticFunctionMember(node: ts.Node): boolean {\n if (ts.isMethodDeclaration(node)) return hasStaticModifier(node);\n if (ts.isPropertyDeclaration(node) && hasStaticModifier(node)) {\n const init = node.initializer;\n return init !== undefined && (ts.isArrowFunction(init) || ts.isFunctionExpression(init));\n }\n return false;\n}\n\n// Display name of a static member for the violation message.\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nfunction staticMemberName(node: ts.MethodDeclaration | ts.PropertyDeclaration): string {\n return ts.isIdentifier(node.name) ? node.name.text : '<static>';\n}\n\n// The violation line (or the line just above it) carries the disable comment.\nfunction hasDisableOnLine(fileLines: string[], lineNumber: number): boolean {\n const current = fileLines[lineNumber - 1] ?? '';\n const previous = lineNumber >= 2 ? (fileLines[lineNumber - 2] ?? '') : '';\n return hasDisable(current, RULE_NAMES.NO_FUNCTION_OUTSIDE_CLASS)\n || hasDisable(previous, RULE_NAMES.NO_FUNCTION_OUTSIDE_CLASS);\n}\n\nfunction recordViolation(\n node: ts.Node,\n context: string,\n fileLines: string[],\n sourceFile: ts.SourceFile,\n violations: FnViolationInfo[],\n disableAllowed: boolean,\n): void {\n const startPos = node.getStart(sourceFile);\n if (startPos < 0) return;\n const pos = sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n const column = pos.character + 1;\n const disabled = hasDisableOnLine(fileLines, line);\n // When disableAllowed is false, a disable comment does NOT clear the violation.\n const effectiveDisabled = disableAllowed ? disabled : false;\n violations.push({ line, column, context, hasDisableComment: effectiveDisabled });\n}\n\n// Report a module-scope const whose initializer is an arrow / function-expression (a function\n// assigned to a top-level const). Non-function consts are left alone.\nfunction checkTopLevelConst(\n node: ts.VariableStatement,\n fileLines: string[],\n sourceFile: ts.SourceFile,\n violations: FnViolationInfo[],\n disableAllowed: boolean,\n): void {\n for (const decl of node.declarationList.declarations) {\n const init = decl.initializer;\n if (!init) continue;\n if (!ts.isArrowFunction(init) && !ts.isFunctionExpression(init)) continue;\n const name = ts.isIdentifier(decl.name) ? decl.name.text : '<fn>';\n recordViolation(decl, `const ${name} = <function> at module scope (outside any class)`, fileLines, sourceFile, violations, disableAllowed);\n }\n}\n\n// AST scan: a node is a violation only when its parent is the SourceFile (module scope).\nexport function findFunctionsOutsideClassInSource(content: string, filePath: string, disableAllowed: boolean): FnViolationInfo[] {\n if (isDeclarationFile(filePath)) return [];\n const fileLines = content.split('\\n');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n const violations: FnViolationInfo[] = [];\n\n function visit(node: ts.Node): void {\n if (ts.isFunctionDeclaration(node) && ts.isSourceFile(node.parent) && !hasDeclareModifier(node)) {\n const name = node.name?.text ?? '<anonymous>';\n recordViolation(node, `function ${name}() declared at module scope (outside any class)`, fileLines, sourceFile, violations, disableAllowed);\n }\n if (ts.isVariableStatement(node) && ts.isSourceFile(node.parent) && !hasDeclareModifier(node)) {\n checkTopLevelConst(node, fileLines, sourceFile, violations, disableAllowed);\n }\n if (isStaticFunctionMember(node) && !hasDeclareModifier(node)) {\n const name = staticMemberName(node as ts.MethodDeclaration | ts.PropertyDeclaration);\n recordViolation(node, `static ${name}() — a static method can't be injected; make it an instance method and inject the class`, fileLines, sourceFile, violations, disableAllowed);\n }\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return violations;\n}\n\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nexport function findFunctionsOutsideClassInFile(filePath: string, workspaceRoot: string, disableAllowed: boolean, allowedPaths: string[]): FnViolationInfo[] {\n if (isTestFile(filePath)) return [];\n if (isPathExcluded(filePath, allowedPaths)) return [];\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n const content = fs.readFileSync(fullPath, 'utf-8');\n return findFunctionsOutsideClassInSource(content, filePath, disableAllowed);\n}\n\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nfunction findViolationsForModifiedCode(workspaceRoot: string, changedFiles: string[], base: string, head: string | undefined, disableAllowed: boolean, allowedPaths: string[]): FnViolation[] {\n const violations: FnViolation[] = [];\n for (const file of changedFiles) {\n const changedLines = getChangedLineNumbers(getFileDiff(workspaceRoot, file, base, head));\n if (changedLines.size === 0) continue;\n for (const v of findFunctionsOutsideClassInFile(file, workspaceRoot, disableAllowed, allowedPaths)) {\n if (disableAllowed && v.hasDisableComment) continue;\n if (!changedLines.has(v.line)) continue;\n violations.push({ file, line: v.line, column: v.column, context: v.context });\n }\n }\n return violations;\n}\n\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nfunction findViolationsForModifiedFiles(workspaceRoot: string, changedFiles: string[], disableAllowed: boolean, allowedPaths: string[]): FnViolation[] {\n const violations: FnViolation[] = [];\n for (const file of changedFiles) {\n for (const v of findFunctionsOutsideClassInFile(file, workspaceRoot, disableAllowed, allowedPaths)) {\n if (disableAllowed && v.hasDisableComment) continue;\n violations.push({ file, line: v.line, column: v.column, context: v.context });\n }\n }\n return violations;\n}\n\nfunction reportViolations(violations: FnViolation[], mode: ModifiedCodeMode, disableAllowed: boolean): void {\n console.error('');\n console.error('❌ Function(s) created outside a class!');\n console.error('');\n console.error(SHARED_MESSAGE);\n console.error('');\n for (const v of violations) {\n console.error(` ❌ ${v.file}:${v.line}:${v.column}`);\n console.error(` ${v.context}`);\n }\n console.error('');\n console.error(disableAllowed\n ? ' Escape hatch (use sparingly): // webpieces-disable no-function-outside-class -- <reason>'\n : ' Escape hatch: DISABLED (disableAllowed: false)');\n console.error(' Whole-tree exemption (e.g. React): add a glob to no-function-outside-class.allowedPaths in webpieces.config.json');\n console.error(`\\n Current mode: ${mode}\\n`);\n}\n\nfunction resolveMode(normalMode: ModifiedCodeMode, epoch: number | undefined, branchPattern: string | undefined): ModifiedCodeMode {\n if (normalMode === 'OFF') return normalMode;\n const skip = shouldSkipRule(epoch, branchPattern);\n if (skip.skip) {\n console.log(`\\n⏭️ Skipping no-function-outside-class validation (${skip.reason})\\n`);\n return 'OFF';\n }\n return normalMode;\n}\n\nasync function runValidatorImpl(options: NoFunctionOutsideClassConfig, workspaceRoot: string): Promise<ExecutorResult> {\n const mode: ModifiedCodeMode = resolveMode(options.mode ?? 'OFF', options.ignoreModifiedUntilEpoch, options.ignoreRuleWhileOnBranch);\n const disableAllowed = options.disableAllowed ?? true;\n const allowedPaths = options.allowedPaths ?? [];\n\n if (mode === 'OFF') {\n console.log('\\n⏭️ Skipping no-function-outside-class validation (mode: OFF)\\n');\n return { success: true };\n }\n\n console.log('\\n📏 Validating No Function Outside Class\\n');\n console.log(` Mode: ${mode}`);\n\n let base = process.env['NX_BASE'];\n const head = process.env['NX_HEAD'];\n if (!base) {\n base = detectBase(workspaceRoot) ?? undefined;\n if (!base) {\n console.log('\\n⏭️ Skipping no-function-outside-class validation (could not detect base branch)\\n');\n return { success: true };\n }\n }\n\n console.log(` Base: ${base}`);\n console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}\\n`);\n\n const changedFiles = getChangedFiles(workspaceRoot, base, head);\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: FnViolation[] = [];\n if (mode === 'NEW_AND_MODIFIED_CODE') {\n violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head, disableAllowed, allowedPaths);\n } else if (mode === 'NEW_AND_MODIFIED_FILES') {\n violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed, allowedPaths);\n }\n\n if (violations.length === 0) {\n console.log('✅ No function-outside-class violations found');\n return { success: true };\n }\n\n reportViolations(violations, mode, disableAllowed);\n return { success: false };\n}\n\n@injectable(bindingScopeValues.Singleton)\nexport class NoFunctionOutsideClassValidator extends CodeValidator<NoFunctionOutsideClassConfig> {\n constructor(config: NoFunctionOutsideClassConfig) {\n super(config, 'no-function-outside-class');\n }\n\n async run(workspaceRoot: string): Promise<ExecutorResult> {\n return runValidatorImpl(this.config, workspaceRoot);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validate-no-function-outside-class.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/validate-no-function-outside-class.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate No Function Outside Class\n *\n * Flags a function CREATED OUTSIDE A CLASS at module scope, or a STATIC class member:\n * - a top-level `function foo()` / `export function foo()` declaration,\n * - a top-level `const foo = () => {}` / `const foo = function(){}`, and\n * - a `static foo() {}` method or `static foo = () => {}` field-function (a static member\n * belongs to the class object, not an instance, so it can't be injected either).\n *\n * WHY: webpieces DI + @DocumentDesign only work when behavior lives in injectable classes that can be\n * wired into each other. A module-scope function is a dead-end the DI graph can't reach — move the\n * logic onto a `@provideSingleton()` class and inject it instead.\n *\n * Uses the TypeScript AST so class-membership is checked precisely (not a regex heuristic): a node is a\n * violation only when its parent is the SourceFile (module scope). That automatically EXEMPTS inline\n * callbacks (`arr.map(x => x)`), promise handlers, nested functions inside methods, and functions\n * nested in other functions — their parent is a Block/CallExpression, never the SourceFile.\n *\n * ALLOWED (skip — NOT violations)\n * - Any function/arrow nested inside a class method, another function, or a callback.\n * - Non-function top-level consts: `const SCHEMA = z.object({})`, `const MAX = 5`, object/array literals.\n * - Ambient declarations (`declare function ...`) and whole `*.d.ts` files.\n * - Test files (*.test.ts, *.spec.ts, __tests__/**).\n * - Files under a configured `allowedPaths` glob (e.g. React component/hook trees that legitimately use\n * module-scope functions). Matched with the shared `isPathExcluded` glob/prefix/segment semantics.\n * - Lines with `// webpieces-disable no-function-outside-class -- <reason>` (when disableAllowed).\n *\n * MODES (AST + LINE-SCOPED)\n * - OFF: Skip.\n * - NEW_AND_MODIFIED_CODE: Flag only on changed lines (diff hunks).\n * - NEW_AND_MODIFIED_FILES: Flag every occurrence in any modified file.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as ts from 'typescript';\nimport { hasDisable, RULE_NAMES, NoFunctionOutsideClassConfig, ModifiedCodeMode, detectBase, getChangedFiles, getFileDiff, getChangedLineNumbers, isPathExcluded } from '@webpieces/rules-config';\nimport { CodeValidator, ExecutorResult } from './code-validator';\nimport { injectable, bindingScopeValues } from 'inversify';\nimport { shouldSkipRule } from './resolve-mode';\n\nconst SHARED_MESSAGE = `Functions must live inside a class as INSTANCE methods — a function created at module scope, OR a\nstatic method, can't be injected, so webpieces DI + @DocumentDesign can't wire it into anything. A\nstatic method is just a module-scope function wearing a class as a namespace.\n BAD: export function computeTotal(cart: Cart): number { ... }\n BAD: export class CartMath { static computeTotal(cart: Cart): number { ... } } // static = not injectable\n GOOD: @injectable(bindingScopeValues.Singleton)\n export class CartService { computeTotal(cart: Cart): number { ... } }\nThen inject CartService where you need it. Inline callbacks (arr.map(x => x)), promise handlers, and\nfunctions nested inside a method are fine — only MODULE-SCOPE function declarations, top-level\nconst-assigned functions, and STATIC methods/field-functions are flagged.`;\n\ninterface FnViolation {\n file: string;\n line: number;\n column: number;\n context: string;\n}\n\ninterface FnViolationInfo {\n line: number;\n column: number;\n context: string;\n hasDisableComment: boolean;\n}\n\nfunction isTestFile(filePath: string): boolean {\n return filePath.includes('.spec.ts') || filePath.includes('.test.ts') || filePath.includes('__tests__/');\n}\n\nfunction isDeclarationFile(filePath: string): boolean {\n return filePath.endsWith('.d.ts');\n}\n\n// True for a node carrying a `declare` modifier (ambient signature — not a real definition).\nfunction hasDeclareModifier(node: ts.Node): boolean {\n if (!ts.canHaveModifiers(node)) return false;\n const mods = ts.getModifiers(node);\n return mods?.some((m: ts.Modifier): boolean => m.kind === ts.SyntaxKind.DeclareKeyword) ?? false;\n}\n\n// True for a class member carrying the `static` modifier. A static method/field-function belongs\n// to the class object, not an instance, so it can't be injected — it is procedural code wearing a\n// class as a namespace, and is flagged the same as a module-scope function.\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nfunction hasStaticModifier(node: ts.Node): boolean {\n if (!ts.canHaveModifiers(node)) return false;\n const mods = ts.getModifiers(node);\n return mods?.some((m: ts.Modifier): boolean => m.kind === ts.SyntaxKind.StaticKeyword) ?? false;\n}\n\n// A `static` method, or a `static` field initialized to an arrow/function-expression, on a class.\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nfunction isStaticFunctionMember(node: ts.Node): boolean {\n if (ts.isMethodDeclaration(node)) return hasStaticModifier(node);\n if (ts.isPropertyDeclaration(node) && hasStaticModifier(node)) {\n const init = node.initializer;\n return init !== undefined && (ts.isArrowFunction(init) || ts.isFunctionExpression(init));\n }\n return false;\n}\n\n// Display name of a static member for the violation message.\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nfunction staticMemberName(node: ts.MethodDeclaration | ts.PropertyDeclaration): string {\n return ts.isIdentifier(node.name) ? node.name.text : '<static>';\n}\n\n// The violation line (or the line just above it) carries the disable comment.\nfunction hasDisableOnLine(fileLines: string[], lineNumber: number): boolean {\n const current = fileLines[lineNumber - 1] ?? '';\n const previous = lineNumber >= 2 ? (fileLines[lineNumber - 2] ?? '') : '';\n return hasDisable(current, RULE_NAMES.NO_FUNCTION_OUTSIDE_CLASS)\n || hasDisable(previous, RULE_NAMES.NO_FUNCTION_OUTSIDE_CLASS);\n}\n\nfunction recordViolation(\n node: ts.Node,\n context: string,\n fileLines: string[],\n sourceFile: ts.SourceFile,\n violations: FnViolationInfo[],\n disableAllowed: boolean,\n): void {\n const startPos = node.getStart(sourceFile);\n if (startPos < 0) return;\n const pos = sourceFile.getLineAndCharacterOfPosition(startPos);\n const line = pos.line + 1;\n const column = pos.character + 1;\n const disabled = hasDisableOnLine(fileLines, line);\n // When disableAllowed is false, a disable comment does NOT clear the violation.\n const effectiveDisabled = disableAllowed ? disabled : false;\n violations.push({ line, column, context, hasDisableComment: effectiveDisabled });\n}\n\n// Report a module-scope const whose initializer is an arrow / function-expression (a function\n// assigned to a top-level const). Non-function consts are left alone.\nfunction checkTopLevelConst(\n node: ts.VariableStatement,\n fileLines: string[],\n sourceFile: ts.SourceFile,\n violations: FnViolationInfo[],\n disableAllowed: boolean,\n): void {\n for (const decl of node.declarationList.declarations) {\n const init = decl.initializer;\n if (!init) continue;\n if (!ts.isArrowFunction(init) && !ts.isFunctionExpression(init)) continue;\n const name = ts.isIdentifier(decl.name) ? decl.name.text : '<fn>';\n recordViolation(decl, `const ${name} = <function> at module scope (outside any class)`, fileLines, sourceFile, violations, disableAllowed);\n }\n}\n\n// AST scan: a node is a violation only when its parent is the SourceFile (module scope).\nexport function findFunctionsOutsideClassInSource(content: string, filePath: string, disableAllowed: boolean): FnViolationInfo[] {\n if (isDeclarationFile(filePath)) return [];\n const fileLines = content.split('\\n');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n const violations: FnViolationInfo[] = [];\n\n function visit(node: ts.Node): void {\n if (ts.isFunctionDeclaration(node) && ts.isSourceFile(node.parent) && !hasDeclareModifier(node)) {\n const name = node.name?.text ?? '<anonymous>';\n recordViolation(node, `function ${name}() declared at module scope (outside any class)`, fileLines, sourceFile, violations, disableAllowed);\n }\n if (ts.isVariableStatement(node) && ts.isSourceFile(node.parent) && !hasDeclareModifier(node)) {\n checkTopLevelConst(node, fileLines, sourceFile, violations, disableAllowed);\n }\n if (isStaticFunctionMember(node) && !hasDeclareModifier(node)) {\n const name = staticMemberName(node as ts.MethodDeclaration | ts.PropertyDeclaration);\n recordViolation(node, `static ${name}() — a static method can't be injected; make it an instance method and inject the class`, fileLines, sourceFile, violations, disableAllowed);\n }\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return violations;\n}\n\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nexport function findFunctionsOutsideClassInFile(filePath: string, workspaceRoot: string, disableAllowed: boolean, allowedPaths: string[]): FnViolationInfo[] {\n if (isTestFile(filePath)) return [];\n if (isPathExcluded(filePath, allowedPaths)) return [];\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n const content = fs.readFileSync(fullPath, 'utf-8');\n return findFunctionsOutsideClassInSource(content, filePath, disableAllowed);\n}\n\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nfunction findViolationsForModifiedCode(workspaceRoot: string, changedFiles: string[], base: string, head: string | undefined, disableAllowed: boolean, allowedPaths: string[]): FnViolation[] {\n const violations: FnViolation[] = [];\n for (const file of changedFiles) {\n const changedLines = getChangedLineNumbers(getFileDiff(workspaceRoot, file, base, head));\n if (changedLines.size === 0) continue;\n for (const v of findFunctionsOutsideClassInFile(file, workspaceRoot, disableAllowed, allowedPaths)) {\n if (disableAllowed && v.hasDisableComment) continue;\n if (!changedLines.has(v.line)) continue;\n violations.push({ file, line: v.line, column: v.column, context: v.context });\n }\n }\n return violations;\n}\n\n// webpieces-disable no-function-outside-class -- the rule engine is inherently functional; validators can't be class members\nfunction findViolationsForModifiedFiles(workspaceRoot: string, changedFiles: string[], disableAllowed: boolean, allowedPaths: string[]): FnViolation[] {\n const violations: FnViolation[] = [];\n for (const file of changedFiles) {\n for (const v of findFunctionsOutsideClassInFile(file, workspaceRoot, disableAllowed, allowedPaths)) {\n if (disableAllowed && v.hasDisableComment) continue;\n violations.push({ file, line: v.line, column: v.column, context: v.context });\n }\n }\n return violations;\n}\n\nfunction reportViolations(violations: FnViolation[], mode: ModifiedCodeMode, disableAllowed: boolean): void {\n console.error('');\n console.error('❌ Function(s) created outside a class!');\n console.error('');\n console.error(SHARED_MESSAGE);\n console.error('');\n for (const v of violations) {\n console.error(` ❌ ${v.file}:${v.line}:${v.column}`);\n console.error(` ${v.context}`);\n }\n console.error('');\n console.error(disableAllowed\n ? ' Escape hatch (use sparingly): // webpieces-disable no-function-outside-class -- <reason>'\n : ' Escape hatch: DISABLED (disableAllowed: false)');\n console.error(' Whole-tree exemption (e.g. React): add a glob to no-function-outside-class.allowedPaths in webpieces.config.json');\n console.error(`\\n Current mode: ${mode}\\n`);\n}\n\nfunction resolveMode(normalMode: ModifiedCodeMode, epoch: number | undefined, branchPattern: string | undefined): ModifiedCodeMode {\n if (normalMode === 'OFF') return normalMode;\n const skip = shouldSkipRule(epoch, branchPattern);\n if (skip.skip) {\n console.log(`\\n⏭️ Skipping no-function-outside-class validation (${skip.reason})\\n`);\n return 'OFF';\n }\n return normalMode;\n}\n\nasync function runValidatorImpl(options: NoFunctionOutsideClassConfig, workspaceRoot: string): Promise<ExecutorResult> {\n const mode: ModifiedCodeMode = resolveMode(options.mode ?? 'OFF', options.turnOffRuleUntilEpoch, (options.turnOffRuleWhileOnBranch ?? undefined));\n const disableAllowed = options.disableAllowed ?? true;\n const allowedPaths = options.allowedPaths ?? [];\n\n if (mode === 'OFF') {\n console.log('\\n⏭️ Skipping no-function-outside-class validation (mode: OFF)\\n');\n return { success: true };\n }\n\n console.log('\\n📏 Validating No Function Outside Class\\n');\n console.log(` Mode: ${mode}`);\n\n let base = process.env['NX_BASE'];\n const head = process.env['NX_HEAD'];\n if (!base) {\n base = detectBase(workspaceRoot) ?? undefined;\n if (!base) {\n console.log('\\n⏭️ Skipping no-function-outside-class validation (could not detect base branch)\\n');\n return { success: true };\n }\n }\n\n console.log(` Base: ${base}`);\n console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}\\n`);\n\n const changedFiles = getChangedFiles(workspaceRoot, base, head);\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: FnViolation[] = [];\n if (mode === 'NEW_AND_MODIFIED_CODE') {\n violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head, disableAllowed, allowedPaths);\n } else if (mode === 'NEW_AND_MODIFIED_FILES') {\n violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed, allowedPaths);\n }\n\n if (violations.length === 0) {\n console.log('✅ No function-outside-class violations found');\n return { success: true };\n }\n\n reportViolations(violations, mode, disableAllowed);\n return { success: false };\n}\n\n@injectable(bindingScopeValues.Singleton)\nexport class NoFunctionOutsideClassValidator extends CodeValidator<NoFunctionOutsideClassConfig> {\n constructor(config: NoFunctionOutsideClassConfig) {\n super(config, 'no-function-outside-class');\n }\n\n async run(workspaceRoot: string): Promise<ExecutorResult> {\n return runValidatorImpl(this.config, workspaceRoot);\n }\n}\n"]}
|
|
@@ -190,7 +190,7 @@ function resolveMode(normalMode, epoch, branchPattern) {
|
|
|
190
190
|
return normalMode;
|
|
191
191
|
}
|
|
192
192
|
async function runInternal(options, workspaceRoot) {
|
|
193
|
-
const mode = resolveMode(options.mode ?? 'OFF', options.
|
|
193
|
+
const mode = resolveMode(options.mode ?? 'OFF', options.turnOffRuleUntilEpoch, (options.turnOffRuleWhileOnBranch ?? undefined));
|
|
194
194
|
const disableAllowed = options.disableAllowed ?? true;
|
|
195
195
|
if (mode === 'OFF') {
|
|
196
196
|
console.log('\n\u23ed\ufe0f Skipping no-implicit-any validation (mode: OFF)');
|