@trackunit/eslint-plugin-trackunit 0.6.53 → 0.6.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +5 -4
  3. package/migrations/entry.js +3 -0
  4. package/migrations.json +3 -0
  5. package/package.json +4 -2
  6. package/src/index.d.ts +1 -1
  7. package/src/index.js +2 -1
  8. package/src/lib/config/index.d.ts +18 -0
  9. package/src/lib/config/plugins.d.ts +3 -0
  10. package/src/lib/config/presets/base.d.ts +11 -0
  11. package/src/lib/config/presets/base.js +1 -0
  12. package/src/lib/config/presets/react.d.ts +7 -0
  13. package/src/lib/config/presets/react.js +3 -0
  14. package/src/lib/rules/no-deprecated-graphql-fields/no-deprecated-graphql-fields.d.ts +4 -0
  15. package/src/lib/rules/no-deprecated-graphql-fields/no-deprecated-graphql-fields.js +104 -0
  16. package/src/lib/rules/no-deprecated-graphql-fields/schema-cache.d.ts +3 -0
  17. package/src/lib/rules/no-deprecated-graphql-fields/schema-cache.js +31 -0
  18. package/src/lib/rules-map.d.ts +3 -0
  19. package/src/lib/rules-map.js +2 -0
  20. package/src/index.js.map +0 -1
  21. package/src/lib/config/fragments/ignores.js.map +0 -1
  22. package/src/lib/config/fragments/import-rules.js.map +0 -1
  23. package/src/lib/config/fragments/jest-overrides.js.map +0 -1
  24. package/src/lib/config/fragments/jsdoc-rules.js.map +0 -1
  25. package/src/lib/config/fragments/module-boundaries.js.map +0 -1
  26. package/src/lib/config/fragments/no-direct-storage-access.js.map +0 -1
  27. package/src/lib/config/fragments/react-rules.js.map +0 -1
  28. package/src/lib/config/fragments/restricted-imports.js.map +0 -1
  29. package/src/lib/config/fragments/testing-library.js.map +0 -1
  30. package/src/lib/config/fragments/typescript-rules.js.map +0 -1
  31. package/src/lib/config/index.js.map +0 -1
  32. package/src/lib/config/plugins.js.map +0 -1
  33. package/src/lib/config/presets/base.js.map +0 -1
  34. package/src/lib/config/presets/e2e.js.map +0 -1
  35. package/src/lib/config/presets/react.js.map +0 -1
  36. package/src/lib/config/presets/server.js.map +0 -1
  37. package/src/lib/config/utils.js.map +0 -1
  38. package/src/lib/config-helpers/create-skip-when.js.map +0 -1
  39. package/src/lib/rules/component-name-matches-filename/component-name-matches-filename.js.map +0 -1
  40. package/src/lib/rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array.js.map +0 -1
  41. package/src/lib/rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match.js.map +0 -1
  42. package/src/lib/rules/no-internal-barrel-files/no-internal-barrel-files.js.map +0 -1
  43. package/src/lib/rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public.js.map +0 -1
  44. package/src/lib/rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks.js.map +0 -1
  45. package/src/lib/rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop.js.map +0 -1
  46. package/src/lib/rules/no-typescript-assertion/no-typescript-assertion.js.map +0 -1
  47. package/src/lib/rules/one-component-per-file/one-component-per-file.js.map +0 -1
  48. package/src/lib/rules/prefer-destructured-imports/prefer-destructured-imports.js.map +0 -1
  49. package/src/lib/rules/prefer-event-specific-callback-naming/name-suggestion-strategies.js.map +0 -1
  50. package/src/lib/rules/prefer-event-specific-callback-naming/prefer-event-specific-callback-naming.js.map +0 -1
  51. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/string-based.js.map +0 -1
  52. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/type-based.js.map +0 -1
  53. package/src/lib/rules/prefer-event-specific-callback-naming/utils.js.map +0 -1
  54. package/src/lib/rules/prefer-field-components/prefer-field-components.js.map +0 -1
  55. package/src/lib/rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props.js.map +0 -1
  56. package/src/lib/rules/require-classname-alternatives/require-classname-alternatives.js.map +0 -1
  57. package/src/lib/rules/require-component-prop-contracts/require-component-prop-contracts.js.map +0 -1
  58. package/src/lib/rules/require-list-item-virtualization-props/require-list-item-virtualization-props.js.map +0 -1
  59. package/src/lib/rules/require-optional-prop-initialization/require-optional-prop-initialization.js.map +0 -1
  60. package/src/lib/rules/require-optional-prop-initialization/suggestion-utils.js.map +0 -1
  61. package/src/lib/rules/require-storybook-folder-landing-page/require-storybook-folder-landing-page.js.map +0 -1
  62. package/src/lib/rules-map.js.map +0 -1
  63. package/src/lib/utils/ast-utils.js.map +0 -1
  64. package/src/lib/utils/classname-utils.js.map +0 -1
  65. package/src/lib/utils/component-utils.js.map +0 -1
  66. package/src/lib/utils/file-utils.js.map +0 -1
  67. package/src/lib/utils/import-utils.js.map +0 -1
  68. package/src/lib/utils/nx-utils.js.map +0 -1
  69. package/src/lib/utils/package-utils.js.map +0 -1
  70. package/src/lib/utils/typescript-utils.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"prefer-field-components.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/prefer-field-components/prefer-field-components.ts"],"names":[],"mappings":"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","sourcesContent":["import { AST_NODE_TYPES, ESLintUtils, TSESTree } from \"@typescript-eslint/utils\";\nimport { findImportDeclaration, getImportSpecifiers } from \"../../utils/import-utils\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}/README.md`\n);\n\ntype MessageIds = \"preferFieldComponent\";\n\nconst FORM_COMPONENTS_PACKAGE = \"@trackunit/react-form-components\";\nconst REACT_COMPONENTS_PACKAGE = \"@trackunit/react-components\";\n\n/**\n * Map of base component names to their recommended Field component replacements\n * used in the error message (human-readable, may contain alternatives).\n */\nconst BASE_TO_FIELD_MESSAGE_MAP: Record<string, string> = {\n BaseSelect: \"SelectField (or MultiSelectField for multi-select)\",\n CreatableSelect: \"CreatableSelectField\",\n BaseInput: \"TextField (or the appropriate *Field component for your input type)\",\n TextBaseInput: \"TextField\",\n NumberBaseInput: \"NumberField\",\n DateBaseInput: \"DateField\",\n PhoneBaseInput: \"PhoneField\",\n TextAreaBaseInput: \"TextAreaField\",\n PasswordBaseInput: \"PasswordField\",\n EmailBaseInput: \"EmailField\",\n UrlBaseInput: \"UrlField\",\n};\n\n/**\n * Map used for autofix — always resolves to a single concrete component name.\n *\n * NOTE: BaseSelect and CreatableSelect are intentionally excluded here.\n * SelectField and CreatableSelectField have different value/onChange APIs\n * compared to their base counterparts:\n * - BaseSelect uses `value={optionObject}` and `onChange={(option) => ...}`\n * - SelectField uses `value={rawValue}` and `onChange={(event) => ...}`\n * Auto-fixing would silently break the component's behaviour.\n *\n * BaseSelect with isMulti → MultiSelectField IS compatible and is handled\n * separately in getAutofixFieldName().\n */\nconst BASE_TO_FIELD_AUTOFIX_MAP: Record<string, string> = {\n BaseInput: \"TextField\",\n TextBaseInput: \"TextField\",\n NumberBaseInput: \"NumberField\",\n DateBaseInput: \"DateField\",\n PhoneBaseInput: \"PhoneField\",\n TextAreaBaseInput: \"TextAreaField\",\n PasswordBaseInput: \"PasswordField\",\n EmailBaseInput: \"EmailField\",\n UrlBaseInput: \"UrlField\",\n};\n\nconst BASE_COMPONENT_NAMES = new Set(Object.keys(BASE_TO_FIELD_MESSAGE_MAP));\n\n/**\n * Component names that act as a manual label above a base input/select.\n */\nconst LABEL_COMPONENT_NAMES = new Set([\"Label\", \"Text\"]);\n\n/**\n * Get the JSX element name from a JSXOpeningElement.\n * Returns null for member expressions or namespaced names.\n */\nfunction getJSXElementName(openingElement: TSESTree.JSXOpeningElement): string | null {\n if (openingElement.name.type === AST_NODE_TYPES.JSXIdentifier) {\n return openingElement.name.name;\n }\n return null;\n}\n\n/**\n * Check if a JSX child is a JSXText node that only contains whitespace.\n */\nfunction isWhitespaceText(child: TSESTree.JSXChild): boolean {\n return child.type === AST_NODE_TYPES.JSXText && child.value.trim() === \"\";\n}\n\n/**\n * Check if a JSX child is a label-like element (Label or Text).\n */\nfunction isLabelLikeElement(child: TSESTree.JSXChild): child is TSESTree.JSXElement {\n if (child.type !== AST_NODE_TYPES.JSXElement) {\n return false;\n }\n const name = getJSXElementName(child.openingElement);\n return name !== null && LABEL_COMPONENT_NAMES.has(name);\n}\n\n/**\n * Find the previous non-whitespace sibling in a list of JSX children.\n */\nfunction getPreviousNonWhitespaceSibling(\n children: Array<TSESTree.JSXChild>,\n currentIndex: number\n): TSESTree.JSXChild | null {\n for (let i = currentIndex - 1; i >= 0; i--) {\n const sibling = children[i];\n if (sibling !== undefined && !isWhitespaceText(sibling)) {\n return sibling;\n }\n }\n return null;\n}\n\n/**\n * Check if a JSXOpeningElement has a specific boolean or truthy prop.\n */\nfunction hasJSXProp(openingElement: TSESTree.JSXOpeningElement, propName: string): boolean {\n return openingElement.attributes.some(\n attr =>\n attr.type === AST_NODE_TYPES.JSXAttribute &&\n attr.name.type === AST_NODE_TYPES.JSXIdentifier &&\n attr.name.name === propName\n );\n}\n\ntype LabelContent = { type: \"string\"; value: string } | { type: \"expression\"; text: string };\n\n/**\n * Extract the meaningful label content from a Label/Text element's children.\n *\n * Returns null if the content is too complex to autofix (e.g. multiple meaningful\n * children, or JSX element children).\n */\nfunction extractLabelContent(\n labelElement: TSESTree.JSXElement,\n sourceCode: Readonly<{ getText(node: TSESTree.Node): string }>\n): LabelContent | null {\n // Filter out whitespace-only text children\n const meaningfulChildren = labelElement.children.filter(node => {\n if (node.type === AST_NODE_TYPES.JSXText) {\n return node.value.trim() !== \"\";\n }\n return true;\n });\n\n if (meaningfulChildren.length !== 1) {\n return null; // Complex content — skip autofix\n }\n\n const child = meaningfulChildren[0];\n if (child === undefined) {\n return null;\n }\n\n if (child.type === AST_NODE_TYPES.JSXText) {\n const trimmed = child.value.trim();\n if (trimmed.length === 0) {\n return null;\n }\n return { type: \"string\", value: trimmed };\n }\n\n if (child.type === AST_NODE_TYPES.JSXExpressionContainer) {\n if (child.expression.type === AST_NODE_TYPES.JSXEmptyExpression) {\n return null;\n }\n return { type: \"expression\", text: sourceCode.getText(child.expression) };\n }\n\n return null;\n}\n\n/**\n * Determine the field component name for autofix.\n *\n * Returns null (no autofix) for BaseSelect without isMulti and CreatableSelect,\n * because SelectField/CreatableSelectField have incompatible value/onChange APIs.\n *\n * BaseSelect with isMulti → MultiSelectField is safe because MultiSelectField\n * preserves the same option-object-based value/onChange API as BaseSelect.\n */\nfunction getAutofixFieldName(baseComponentName: string, openingElement: TSESTree.JSXOpeningElement): string | null {\n if (baseComponentName === \"BaseSelect\" && hasJSXProp(openingElement, \"isMulti\")) {\n return \"MultiSelectField\";\n }\n return BASE_TO_FIELD_AUTOFIX_MAP[baseComponentName] ?? null;\n}\n\n/**\n * Build the label prop string for the autofix.\n */\nfunction buildLabelPropValue(content: LabelContent): string {\n switch (content.type) {\n case \"string\":\n return `\"${content.value}\"`;\n case \"expression\":\n return `{${content.text}}`;\n default: {\n const _exhaustiveCheck: never = content;\n return _exhaustiveCheck;\n }\n }\n}\n\n/**\n * Count how many times a component is used as a JSX opening tag in the source text.\n * Uses a regex that matches `<ComponentName` followed by whitespace, `>`, or `/>`.\n */\nfunction countJSXElementUsages(sourceText: string, componentName: string): number {\n const pattern = new RegExp(`<${componentName}(?=[\\\\s/>])`, \"g\");\n const matches = sourceText.match(pattern);\n return matches ? matches.length : 0;\n}\n\n/**\n * Build a new import statement string with the given specifiers, preserving semicolons.\n */\nfunction buildImportStatement(\n sourceCode: Readonly<{ getText(node: TSESTree.Node): string }>,\n importNode: TSESTree.ImportDeclaration,\n specifiers: Iterable<string>\n): string {\n const sortedSpecifiers = Array.from(specifiers).sort().join(\", \");\n const originalText = sourceCode.getText(importNode);\n const semicolon = originalText.trimEnd().endsWith(\";\") ? \";\" : \"\";\n return `import { ${sortedSpecifiers} } from \"${importNode.source.value}\"${semicolon}`;\n}\n\nexport const preferFieldComponents = createRule<[], MessageIds>({\n name: \"prefer-field-components\",\n meta: {\n type: \"suggestion\",\n fixable: \"code\",\n docs: {\n description:\n \"Prefer using Field components (e.g. SelectField, TextField) instead of manually combining Label/Text with base input components (e.g. BaseSelect, BaseInput).\",\n },\n schema: [],\n messages: {\n preferFieldComponent:\n \"Avoid using {{labelComponent}} with {{baseComponent}}. Use {{fieldComponent}} instead, which includes a built-in label via the `label` prop.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const sourceCode = context.sourceCode;\n\n return {\n JSXElement(node: TSESTree.JSXElement) {\n const children = node.children;\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Only look at JSXElement children\n if (child === undefined || child.type !== AST_NODE_TYPES.JSXElement) {\n continue;\n }\n\n const childName = getJSXElementName(child.openingElement);\n\n // Check if this child is a base component\n if (childName === null || !BASE_COMPONENT_NAMES.has(childName)) {\n continue;\n }\n\n // Found a base component — check if the previous non-whitespace sibling is a Label/Text\n const previousSibling = getPreviousNonWhitespaceSibling(children, i);\n\n if (previousSibling === null || !isLabelLikeElement(previousSibling)) {\n continue;\n }\n\n const labelName = getJSXElementName(previousSibling.openingElement);\n const fieldComponentMessage = BASE_TO_FIELD_MESSAGE_MAP[childName] ?? \"the appropriate *Field component\";\n const fieldComponentAutofix = getAutofixFieldName(childName, child.openingElement);\n const labelContent = extractLabelContent(previousSibling, sourceCode);\n\n context.report({\n node: child,\n messageId: \"preferFieldComponent\",\n data: {\n labelComponent: labelName ?? \"Label/Text\",\n baseComponent: childName,\n fieldComponent: fieldComponentMessage,\n },\n fix:\n fieldComponentAutofix !== null && labelContent !== null\n ? fixer => {\n const fixes: Array<ReturnType<typeof fixer.replaceText>> = [];\n const labelPropValue = buildLabelPropValue(labelContent);\n const fullSourceText = sourceCode.getText();\n\n // 1. Replace everything from Label start through the base component's tag name\n // in a single operation: <Label>...</Label>\\n...<BaseSelect → <SelectField label={...}\n fixes.push(\n fixer.replaceTextRange(\n [previousSibling.range[0], child.openingElement.name.range[1]],\n `<${fieldComponentAutofix} label=${labelPropValue}`\n )\n );\n\n // 2. Rename the closing tag if present (for non-self-closing elements)\n if (child.closingElement !== null) {\n fixes.push(fixer.replaceText(child.closingElement.name, fieldComponentAutofix));\n }\n\n // 3. Update imports: add the field component, remove base/label if no longer used.\n // All modifications to the same import declaration are combined into a single fix.\n const baseUsageCount = countJSXElementUsages(fullSourceText, childName);\n const labelUsageCount = labelName !== null ? countJSXElementUsages(fullSourceText, labelName) : 0;\n\n // Handle @trackunit/react-form-components import\n const formImport = findImportDeclaration(sourceCode, FORM_COMPONENTS_PACKAGE);\n if (formImport) {\n const specifiers = getImportSpecifiers(formImport);\n\n // Add field component\n specifiers.add(fieldComponentAutofix);\n\n // Remove base component if this is the only JSX usage\n if (baseUsageCount <= 1) {\n specifiers.delete(childName);\n }\n\n // Remove Label if it's from this package and this is the only JSX usage\n if (labelName === \"Label\" && labelUsageCount <= 1) {\n specifiers.delete(\"Label\");\n }\n\n fixes.push(\n fixer.replaceText(formImport, buildImportStatement(sourceCode, formImport, specifiers))\n );\n }\n\n // Handle @trackunit/react-components import (for Text removal)\n if (labelName === \"Text\" && labelUsageCount <= 1) {\n const reactImport = findImportDeclaration(sourceCode, REACT_COMPONENTS_PACKAGE);\n if (reactImport) {\n const specifiers = getImportSpecifiers(reactImport);\n if (specifiers.has(\"Text\")) {\n specifiers.delete(\"Text\");\n if (specifiers.size === 0) {\n fixes.push(fixer.remove(reactImport));\n } else {\n fixes.push(\n fixer.replaceText(reactImport, buildImportStatement(sourceCode, reactImport, specifiers))\n );\n }\n }\n }\n }\n\n return fixes;\n }\n : null,\n });\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"prefer-mouse-event-handler-in-react-props.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ESLint rule: prefer-mouse-event-handler-in-react-props\n *\n * Enforces using MouseEventHandler<T> instead of () => void or (e: MouseEvent) => void\n * for onClick* props in React components. This ensures proper React typing and consistency.\n *\n * Only flags properties in actual React component props, not in hook options or other interfaces.\n *\n * Uses ESLint suggestions (not autofix) to let users choose the appropriate element type.\n */\n\nimport { AST_NODE_TYPES, ESLintUtils, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\nimport * as ts from \"typescript\";\nimport { isReactComponent } from \"../../utils/ast-utils\";\n\ntype SuggestionResult = {\n messageId: \"suggestMouseEventHandler\";\n data: { elementType: string };\n fix: (fixer: TSESLint.RuleFixer) => TSESLint.RuleFix;\n};\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}/${name}.ts`\n);\n\ntype Options = [\n {\n /**\n * Prop names to exempt from this rule.\n *\n * @example [\"onClick\"]\n */\n allowedNames?: ReadonlyArray<string>;\n },\n];\n\ntype MessageIds = \"preferMouseEventHandler\" | \"suggestMouseEventHandler\";\n\n/**\n * Checks if a property name starts with \"onClick\" (case-sensitive).\n */\nconst isOnClickProp = (name: string): boolean => {\n return name.startsWith(\"onClick\");\n};\n\n/**\n * Extracts the element type from a MouseEvent generic type annotation.\n * Returns null if not a MouseEvent type or no generic provided.\n *\n * Examples:\n * - MouseEvent<HTMLButtonElement> -> \"HTMLButtonElement\"\n * - React.MouseEvent<HTMLDivElement> -> \"HTMLDivElement\"\n * - MouseEvent -> null (no generic)\n */\nconst extractElementTypeFromMouseEvent = (typeAnnotation: TSESTree.TypeNode): string | null => {\n if (typeAnnotation.type !== AST_NODE_TYPES.TSTypeReference) {\n return null;\n }\n\n const { typeName, typeArguments } = typeAnnotation;\n\n let isMouseEvent = false;\n\n if (typeName.type === AST_NODE_TYPES.Identifier) {\n isMouseEvent = typeName.name === \"MouseEvent\";\n } else if (typeName.type === AST_NODE_TYPES.TSQualifiedName) {\n isMouseEvent =\n typeName.left.type === AST_NODE_TYPES.Identifier &&\n typeName.left.name === \"React\" &&\n typeName.right.name === \"MouseEvent\";\n }\n\n if (!isMouseEvent) {\n return null;\n }\n\n if (!typeArguments || typeArguments.params.length === 0) {\n return null;\n }\n\n const firstTypeArg = typeArguments.params[0];\n if (firstTypeArg?.type === AST_NODE_TYPES.TSTypeReference) {\n if (firstTypeArg.typeName.type === AST_NODE_TYPES.Identifier) {\n return firstTypeArg.typeName.name;\n }\n }\n\n return null;\n};\n\n/**\n * Checks if a type annotation is a MouseEvent type (with or without generics).\n */\nconst isMouseEventType = (typeAnnotation: TSESTree.TypeNode): boolean => {\n if (typeAnnotation.type !== AST_NODE_TYPES.TSTypeReference) {\n return false;\n }\n\n const { typeName } = typeAnnotation;\n\n if (typeName.type === AST_NODE_TYPES.Identifier) {\n return typeName.name === \"MouseEvent\";\n }\n\n if (typeName.type === AST_NODE_TYPES.TSQualifiedName) {\n return (\n typeName.left.type === AST_NODE_TYPES.Identifier &&\n typeName.left.name === \"React\" &&\n typeName.right.name === \"MouseEvent\"\n );\n }\n\n return false;\n};\n\n/**\n * Checks if a function type returns void.\n */\nconst hasVoidReturn = (funcType: TSESTree.TSFunctionType): boolean => {\n const { returnType } = funcType;\n\n if (!returnType) {\n return true;\n }\n\n const typeAnnotation = returnType.typeAnnotation;\n\n if (typeAnnotation.type === AST_NODE_TYPES.TSVoidKeyword) {\n return true;\n }\n\n return false;\n};\n\ntype AnalysisResult =\n | { shouldFlag: false }\n | {\n shouldFlag: true;\n inferredElementType: string | null;\n typeAnnotationNode: TSESTree.TSFunctionType;\n };\n\n/**\n * Analyzes a TSFunctionType to determine if it should be flagged.\n */\nconst analyzeFunctionType = (funcType: TSESTree.TSFunctionType): AnalysisResult => {\n if (!hasVoidReturn(funcType)) {\n return { shouldFlag: false };\n }\n\n const { params } = funcType;\n\n // Case A: No parameters - () => void\n if (params.length === 0) {\n return {\n shouldFlag: true,\n inferredElementType: null,\n typeAnnotationNode: funcType,\n };\n }\n\n // Case B: Exactly one parameter that is MouseEvent\n if (params.length === 1) {\n const param = params[0];\n\n let paramTypeAnnotation: TSESTree.TypeNode | undefined;\n\n if (param?.type === AST_NODE_TYPES.Identifier && param.typeAnnotation) {\n paramTypeAnnotation = param.typeAnnotation.typeAnnotation;\n }\n\n if (paramTypeAnnotation && isMouseEventType(paramTypeAnnotation)) {\n const elementType = extractElementTypeFromMouseEvent(paramTypeAnnotation);\n return {\n shouldFlag: true,\n inferredElementType: elementType,\n typeAnnotationNode: funcType,\n };\n }\n }\n\n return { shouldFlag: false };\n};\n\n/**\n * Creates suggestion fixes for a given element type.\n */\nconst createSuggestion = (elementType: string, typeAnnotationNode: TSESTree.TSFunctionType): SuggestionResult => {\n return {\n messageId: \"suggestMouseEventHandler\",\n data: { elementType },\n fix: fixer => {\n return fixer.replaceText(typeAnnotationNode, `MouseEventHandler<${elementType}>`);\n },\n };\n};\n\n/**\n * Known valid HTML element types for MouseEventHandler.\n */\nconst VALID_HTML_ELEMENT_TYPES = new Set([\n \"Element\",\n \"HTMLElement\",\n \"HTMLAnchorElement\",\n \"HTMLButtonElement\",\n \"HTMLDivElement\",\n \"HTMLFormElement\",\n \"HTMLImageElement\",\n \"HTMLInputElement\",\n \"HTMLLabelElement\",\n \"HTMLLIElement\",\n \"HTMLParagraphElement\",\n \"HTMLSelectElement\",\n \"HTMLSpanElement\",\n \"HTMLTableElement\",\n \"HTMLTableRowElement\",\n \"HTMLTableCellElement\",\n \"HTMLTextAreaElement\",\n \"HTMLUListElement\",\n \"SVGElement\",\n \"SVGSVGElement\",\n]);\n\n/**\n * Extracts element type from a MouseEventHandler type string.\n */\nconst extractElementTypeFromTypeString = (typeString: string): string | null => {\n const match = typeString.match(/MouseEventHandler<([^>]+)>/);\n if (match?.[1]) {\n const elementType = match[1].trim();\n if (VALID_HTML_ELEMENT_TYPES.has(elementType)) {\n return elementType;\n }\n }\n return null;\n};\n\n/**\n * Tries to infer the element type by finding where the prop is used in JSX.\n */\nconst inferElementTypeFromUsage = (\n propName: string,\n context: TSESLint.RuleContext<MessageIds, ReadonlyArray<unknown>>\n): string | null => {\n try {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n const sourceFile = services.program.getSourceFile(context.filename);\n\n if (!sourceFile) {\n return null;\n }\n\n let inferredType: string | null = null;\n\n const visit = (node: ts.Node): void => {\n if (ts.isJsxAttribute(node)) {\n const attrName = node.name.getText(sourceFile);\n\n if (attrName.startsWith(\"on\")) {\n const initializer = node.initializer;\n\n if (initializer && ts.isJsxExpression(initializer) && initializer.expression) {\n const expr = initializer.expression;\n let referencedName: string | null = null;\n\n if (ts.isIdentifier(expr) && expr.text === propName) {\n referencedName = propName;\n }\n\n if (ts.isArrowFunction(expr) && ts.isCallExpression(expr.body)) {\n const callee = expr.body.expression;\n if (ts.isIdentifier(callee) && callee.text === propName) {\n referencedName = propName;\n }\n }\n\n if (referencedName) {\n const contextualType = checker.getContextualType(expr);\n if (contextualType) {\n const typeString = checker.typeToString(contextualType);\n const elementType = extractElementTypeFromTypeString(typeString);\n if (elementType) {\n inferredType = elementType;\n }\n }\n }\n }\n }\n }\n\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return inferredType;\n } catch {\n return null;\n }\n};\n\n/**\n * Gets onClick* properties from a component's props type annotation.\n */\nconst getOnClickPropsFromType = (\n context: TSESLint.RuleContext<MessageIds, ReadonlyArray<unknown>>,\n typeAnnotation: TSESTree.TypeNode | undefined\n): Array<{ name: string; typeNode: TSESTree.TSFunctionType; propertyNode: TSESTree.Node }> => {\n if (!typeAnnotation) {\n return [];\n }\n\n const result: Array<{ name: string; typeNode: TSESTree.TSFunctionType; propertyNode: TSESTree.Node }> = [];\n\n // Handle inline type literals: ({ onClick }: { onClick: () => void }) => ...\n if (typeAnnotation.type === AST_NODE_TYPES.TSTypeLiteral) {\n for (const member of typeAnnotation.members) {\n if (\n member.type === AST_NODE_TYPES.TSPropertySignature &&\n member.key.type === AST_NODE_TYPES.Identifier &&\n isOnClickProp(member.key.name) &&\n member.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES.TSFunctionType\n ) {\n result.push({\n name: member.key.name,\n typeNode: member.typeAnnotation.typeAnnotation,\n propertyNode: member,\n });\n }\n }\n return result;\n }\n\n // Handle type references: ({ onClick }: ButtonProps) => ...\n if (typeAnnotation.type === AST_NODE_TYPES.TSTypeReference) {\n try {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n const tsNode = services.esTreeNodeToTSNodeMap.get(typeAnnotation);\n const type = checker.getTypeAtLocation(tsNode);\n\n for (const prop of type.getProperties()) {\n if (isOnClickProp(prop.name)) {\n const propType = checker.getTypeOfSymbolAtLocation(prop, tsNode);\n const callSignatures = propType.getCallSignatures();\n\n if (callSignatures.length > 0) {\n // Find the corresponding ESTree node for this property\n const declarations = prop.getDeclarations();\n const decl = declarations?.[0];\n if (decl) {\n const esTreeNode = services.tsNodeToESTreeNodeMap.get(decl);\n if (\n esTreeNode.type === AST_NODE_TYPES.TSPropertySignature &&\n esTreeNode.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES.TSFunctionType\n ) {\n result.push({\n name: prop.name,\n typeNode: esTreeNode.typeAnnotation.typeAnnotation,\n propertyNode: esTreeNode,\n });\n }\n }\n }\n }\n }\n } catch {\n // Type checking failed - silently skip\n }\n }\n\n return result;\n};\n\nexport const preferMouseEventHandlerInReactProps = createRule<Options, MessageIds>({\n name: \"prefer-mouse-event-handler-in-react-props\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Enforce using MouseEventHandler<T> instead of () => void or (e: MouseEvent) => void for onClick* props in React components. \" +\n \"This ensures proper React typing and consistency across the codebase.\",\n },\n hasSuggestions: true,\n schema: [\n {\n type: \"object\",\n properties: {\n allowedNames: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Prop names to exempt from this rule\",\n },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n preferMouseEventHandler: \"Prop '{{propName}}' should use MouseEventHandler<T> instead of {{currentType}}.\",\n suggestMouseEventHandler: \"Use MouseEventHandler<{{elementType}}>\",\n },\n },\n defaultOptions: [\n {\n allowedNames: [],\n },\n ],\n create(context, [options]) {\n const allowedNames = options.allowedNames ?? [];\n\n // Only run on .tsx files\n const filename = context.filename;\n if (!filename.endsWith(\".tsx\")) {\n return {};\n }\n\n // Track reported property nodes to avoid duplicate reports when multiple components use the same interface\n const reportedNodes = new Set<TSESTree.Node>();\n\n const checkComponentProps = (\n _node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n propsParam: TSESTree.Parameter | undefined\n ) => {\n if (!propsParam) {\n return;\n }\n\n let typeAnnotation: TSESTree.TypeNode | undefined;\n\n // Handle both regular parameters (props: Props) and destructured parameters ({prop1, prop2}: Props)\n if (propsParam.type === AST_NODE_TYPES.Identifier || propsParam.type === AST_NODE_TYPES.ObjectPattern) {\n typeAnnotation = propsParam.typeAnnotation?.typeAnnotation;\n } else {\n return;\n }\n\n const onClickProps = getOnClickPropsFromType(context, typeAnnotation);\n\n for (const { name: propName, typeNode, propertyNode } of onClickProps) {\n // Skip if already reported (prevents duplicates when multiple components use the same interface)\n if (reportedNodes.has(propertyNode)) {\n continue;\n }\n\n // Check if it's in the allowed list\n if (allowedNames.includes(propName)) {\n continue;\n }\n\n // Analyze the function type\n const result = analyzeFunctionType(typeNode);\n\n if (!result.shouldFlag) {\n continue;\n }\n\n // Get the current type as a string for the error message\n const sourceCode = context.sourceCode;\n const currentType = sourceCode.getText(typeNode);\n\n // Build suggestions\n const suggestions: Array<SuggestionResult> = [];\n\n let inferredElementType = result.inferredElementType;\n\n if (!inferredElementType) {\n inferredElementType = inferElementTypeFromUsage(propName, context);\n }\n\n if (inferredElementType) {\n suggestions.push(createSuggestion(inferredElementType, result.typeAnnotationNode));\n } else {\n suggestions.push(createSuggestion(\"HTMLButtonElement\", result.typeAnnotationNode));\n suggestions.push(createSuggestion(\"HTMLElement\", result.typeAnnotationNode));\n suggestions.push(createSuggestion(\"HTMLDivElement\", result.typeAnnotationNode));\n }\n\n // Mark as reported to prevent duplicates\n reportedNodes.add(propertyNode);\n\n context.report({\n node: propertyNode,\n messageId: \"preferMouseEventHandler\",\n data: {\n propName,\n currentType,\n },\n suggest: suggestions,\n });\n }\n };\n\n return {\n FunctionDeclaration(node: TSESTree.FunctionDeclaration) {\n if (isReactComponent(node)) {\n checkComponentProps(node, node.params[0]);\n }\n },\n\n ArrowFunctionExpression(node: TSESTree.ArrowFunctionExpression) {\n if (isReactComponent(node)) {\n checkComponentProps(node, node.params[0]);\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"require-classname-alternatives.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/require-classname-alternatives/require-classname-alternatives.ts"],"names":[],"mappings":"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","sourcesContent":["import { AST_NODE_TYPES, ESLintUtils, TSESTree } from \"@typescript-eslint/utils\";\nimport { findClassnameStringsInAttribute, findClassnameStringsInCall } from \"../../utils/classname-utils\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}.ts`\n);\n\ntype MessageIds = \"bannedClassAutoFix\" | \"bannedClassSuggest\" | \"suggestReplacement\";\n\ntype RuleConfig = {\n /** Map of banned class name patterns to their allowed alternatives */\n alternatives: Record<string, Array<string>>;\n /** Optional prefixes to match (e.g., \"bg\", \"text\", \"border\"). If not provided, matches exact class names. */\n prefixes?: Array<string>;\n};\n\ntype Options = [RuleConfig?];\n\n/**\n * Replace a specific pattern in a string with its replacement.\n * Handles both prefix-based patterns (e.g., bg-red-500 -> bg-danger-500)\n * and exact matches.\n */\nfunction replacePattern(value: string, oldPattern: string, newPattern: string, hasPrefixes: boolean): string {\n if (hasPrefixes) {\n // With prefixes, replace -oldPattern- with -newPattern-\n const pattern = new RegExp(`-${oldPattern}(-|$|/)`, \"g\");\n return value.replace(pattern, `-${newPattern}$1`);\n } else {\n // Without prefixes, replace exact word boundaries\n const pattern = new RegExp(`(^|\\\\s)${oldPattern}($|\\\\s)`, \"g\");\n return value.replace(pattern, `$1${newPattern}$2`);\n }\n}\n\n/**\n * Build a regex pattern that matches class names based on configuration.\n *\n * With prefixes: Matches patterns like bg-red-500, text-blue-200, hover:border-green-400\n * Without prefixes: Matches exact class names as standalone words\n */\nfunction buildBannedPattern(bannedPatterns: Array<string>, prefixes?: Array<string>): RegExp {\n const patternList = bannedPatterns.join(\"|\");\n const variantPrefixes =\n \"(?:hover:|focus:|focus-visible:|focus-within:|active:|disabled:|group-hover:|peer-hover:|dark:|light:|sm:|md:|lg:|xl:|2xl:)*\";\n\n if (prefixes && prefixes.length > 0) {\n const prefixPattern = prefixes.join(\"|\");\n // Match: [variant:]prefix-banned[-suffix][/opacity]\n return new RegExp(\n `(?:^|\\\\s)(${variantPrefixes}(?:${prefixPattern})-(${patternList})(?:-[a-zA-Z0-9]+)?(?:\\\\/\\\\d+)?)(?=\\\\s|$|\")`,\n \"g\"\n );\n } else {\n // Exact match: standalone class name\n return new RegExp(`(?:^|\\\\s)(${variantPrefixes}(${patternList}))(?=\\\\s|$|\")`, \"g\");\n }\n}\n\nexport const requireClassnameAlternatives = createRule<Options, MessageIds>({\n name: \"require-classname-alternatives\",\n meta: {\n type: \"problem\",\n fixable: \"code\",\n hasSuggestions: true,\n docs: {\n description: \"Require specific class names to be replaced with alternatives. Configurable via rule options.\",\n },\n messages: {\n bannedClassAutoFix: '\"{{match}}\" is not allowed. Use \"{{alternative}}\" instead.',\n bannedClassSuggest: '\"{{match}}\" is not allowed. Consider using: {{alternatives}}.',\n suggestReplacement: 'Replace with \"{{replacement}}\"',\n },\n schema: [\n {\n type: \"object\",\n properties: {\n alternatives: {\n type: \"object\",\n description: \"Map of banned patterns to their allowed alternatives (array of strings)\",\n additionalProperties: {\n type: \"array\",\n items: { type: \"string\" },\n },\n },\n prefixes: {\n type: \"array\",\n description: \"Prefixes to match (e.g., 'bg', 'text'). If not provided, matches exact class names.\",\n items: { type: \"string\" },\n },\n },\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [],\n create(context) {\n const options = context.options[0];\n\n // Return early if no options or empty alternatives to save compute\n if (!options || Object.keys(options.alternatives).length === 0) {\n return {};\n }\n\n const { alternatives, prefixes } = options;\n const bannedPatterns = Object.keys(alternatives);\n const hasPrefixes = prefixes !== undefined && prefixes.length > 0;\n\n const isBannedPattern = (pattern: string): boolean => pattern in alternatives;\n\n const getAlternatives = (pattern: string): Array<string> => {\n return alternatives[pattern] ?? [];\n };\n\n const isAutoFixable = (pattern: string): boolean => getAlternatives(pattern).length === 1;\n\n const BANNED_PATTERN = buildBannedPattern(bannedPatterns, prefixes);\n\n /**\n * Find all banned pattern usages in a string value\n */\n function findBannedUsages(value: string): Array<{ match: string; pattern: string }> {\n const results: Array<{ match: string; pattern: string }> = [];\n BANNED_PATTERN.lastIndex = 0;\n\n let regexMatch;\n while ((regexMatch = BANNED_PATTERN.exec(value)) !== null) {\n const matchedClass = regexMatch[1];\n const matchedPattern = regexMatch[2];\n if (matchedClass !== undefined && matchedPattern !== undefined && isBannedPattern(matchedPattern)) {\n results.push({\n match: matchedClass.trim(),\n pattern: matchedPattern,\n });\n }\n }\n\n return results;\n }\n\n /**\n * Replace ALL auto-fixable patterns in a string at once\n */\n function replaceAllAutoFixablePatterns(value: string): string {\n let result = value;\n for (const [pattern, alts] of Object.entries(alternatives)) {\n const singleAlternative = alts.length === 1 ? alts[0] : undefined;\n if (singleAlternative) {\n result = replacePattern(result, pattern, singleAlternative, hasPrefixes);\n }\n }\n return result;\n }\n\n // Track which string literals have already had a fix generated\n // to avoid duplicate/conflicting fixes for the same literal\n const fixedLiterals = new WeakSet<TSESTree.Literal | TSESTree.TemplateLiteral>();\n\n /**\n * Create a fixer function that replaces all auto-fixable patterns in a string literal\n */\n function createFixer(stringLiteralNode: TSESTree.Literal | TSESTree.TemplateLiteral) {\n return (fixer: Parameters<NonNullable<Parameters<typeof context.report>[0][\"fix\"]>>[0]) => {\n switch (stringLiteralNode.type) {\n case AST_NODE_TYPES.Literal: {\n const originalValue = stringLiteralNode.value;\n if (typeof originalValue !== \"string\") {\n return null;\n }\n const fixedValue = replaceAllAutoFixablePatterns(originalValue);\n const raw = stringLiteralNode.raw;\n const quote = raw.charAt(0);\n return fixer.replaceText(stringLiteralNode, `${quote}${fixedValue}${quote}`);\n }\n case AST_NODE_TYPES.TemplateLiteral: {\n const fixes: Array<ReturnType<typeof fixer.replaceTextRange>> = [];\n const autoFixablePatterns = Object.entries(alternatives)\n .filter(([, alts]) => alts.length === 1)\n .map(([pattern]) => pattern);\n\n for (const quasi of stringLiteralNode.quasis) {\n const hasFixablePattern = autoFixablePatterns.some(pattern =>\n hasPrefixes ? quasi.value.raw.includes(`-${pattern}`) : quasi.value.raw.includes(pattern)\n );\n if (hasFixablePattern) {\n const fixedRaw = replaceAllAutoFixablePatterns(quasi.value.raw);\n const rangeStart = quasi.range[0] + (quasi.tail ? 1 : 0);\n const rangeEnd = quasi.range[1] - (quasi.tail ? 1 : 0);\n fixes.push(\n fixer.replaceTextRange(\n [rangeStart, rangeEnd],\n quasi.tail ? fixedRaw : fixedRaw + (quasi.value.raw.endsWith(\" \") ? \"\" : \"\")\n )\n );\n }\n }\n return fixes.length > 0 ? fixes : null;\n }\n default:\n return null;\n }\n };\n }\n\n /**\n * Create a suggestion fixer for a specific pattern replacement\n */\n function createSuggestionFixer(\n stringLiteralNode: TSESTree.Literal | TSESTree.TemplateLiteral,\n oldPattern: string,\n newPattern: string\n ) {\n return (fixer: Parameters<NonNullable<Parameters<typeof context.report>[0][\"fix\"]>>[0]) => {\n switch (stringLiteralNode.type) {\n case AST_NODE_TYPES.Literal: {\n const originalValue = stringLiteralNode.value;\n if (typeof originalValue !== \"string\") {\n return null;\n }\n const fixedValue = replacePattern(originalValue, oldPattern, newPattern, hasPrefixes);\n const raw = stringLiteralNode.raw;\n const quote = raw.charAt(0);\n return fixer.replaceText(stringLiteralNode, `${quote}${fixedValue}${quote}`);\n }\n case AST_NODE_TYPES.TemplateLiteral: {\n const fixes: Array<ReturnType<typeof fixer.replaceTextRange>> = [];\n for (const quasi of stringLiteralNode.quasis) {\n const containsPattern = hasPrefixes\n ? quasi.value.raw.includes(`-${oldPattern}`)\n : quasi.value.raw.includes(oldPattern);\n if (containsPattern) {\n const fixedRaw = replacePattern(quasi.value.raw, oldPattern, newPattern, hasPrefixes);\n const rangeStart = quasi.range[0] + (quasi.tail ? 1 : 0);\n const rangeEnd = quasi.range[1] - (quasi.tail ? 1 : 0);\n fixes.push(\n fixer.replaceTextRange(\n [rangeStart, rangeEnd],\n quasi.tail ? fixedRaw : fixedRaw + (quasi.value.raw.endsWith(\" \") ? \"\" : \"\")\n )\n );\n }\n }\n return fixes.length > 0 ? fixes : null;\n }\n default:\n return null;\n }\n };\n }\n\n /**\n * Report banned pattern usages for a given node and value.\n * - Auto-fixable patterns (1 alternative): applies fix automatically\n * - Multi-alternative patterns: shows suggestions in editor quick-fix menu\n */\n function checkAndReport(\n node: TSESTree.Node,\n value: string,\n stringLiteralNode?: TSESTree.Literal | TSESTree.TemplateLiteral\n ): void {\n const usages = findBannedUsages(value);\n let fixProvided = false;\n\n for (const usage of usages) {\n const patternIsAutoFixable = isAutoFixable(usage.pattern);\n const patternAlternatives = getAlternatives(usage.pattern);\n\n let fix: Parameters<typeof context.report>[0][\"fix\"];\n let suggest: Parameters<typeof context.report>[0][\"suggest\"];\n\n if (stringLiteralNode) {\n if (patternIsAutoFixable && !fixProvided && !fixedLiterals.has(stringLiteralNode)) {\n fixedLiterals.add(stringLiteralNode);\n fixProvided = true;\n fix = createFixer(stringLiteralNode);\n }\n\n if (!patternIsAutoFixable) {\n suggest = patternAlternatives.map(alternative => ({\n messageId: \"suggestReplacement\" as const,\n data: { replacement: replacePattern(usage.match, usage.pattern, alternative, hasPrefixes) },\n fix: createSuggestionFixer(stringLiteralNode, usage.pattern, alternative),\n }));\n }\n }\n\n if (patternIsAutoFixable) {\n const singleAlternative = patternAlternatives[0];\n context.report({\n node,\n messageId: \"bannedClassAutoFix\",\n data: {\n match: usage.match,\n alternative: singleAlternative ?? \"\",\n },\n fix,\n });\n } else {\n context.report({\n node,\n messageId: \"bannedClassSuggest\",\n data: {\n match: usage.match,\n alternatives: patternAlternatives.join(\", \"),\n },\n suggest,\n });\n }\n }\n }\n\n return {\n JSXAttribute(node: TSESTree.JSXAttribute) {\n const locations = findClassnameStringsInAttribute(node);\n for (const location of locations) {\n checkAndReport(location.reportNode, location.value, location.fixNode);\n }\n },\n\n CallExpression(node: TSESTree.CallExpression) {\n const locations = findClassnameStringsInCall(node);\n for (const location of locations) {\n checkAndReport(location.reportNode, location.value, location.fixNode);\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"require-component-prop-contracts.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/require-component-prop-contracts/require-component-prop-contracts.ts"],"names":[],"mappings":"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","sourcesContent":["import { AST_NODE_TYPES, ESLintUtils, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as ts from \"typescript\";\nimport { functionReturnsIntrinsicJSX, isReactComponent } from \"../../utils/ast-utils\";\nimport { getProjectMetadata } from \"../../utils/nx-utils\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}/${name}.ts`\n);\n\ntype Options = [\n {\n requiredProps?: ReadonlyArray<string>;\n requiredInterfaces?: ReadonlyArray<string>;\n restrictToComponentsWithJsxReturn?: boolean;\n },\n];\n\ntype MessageIds = \"missingPropContracts\";\n\ntype ComponentCandidate = {\n componentName: string;\n node: TSESTree.Node;\n propsType: TSESTree.TypeNode | null;\n};\n\ntype TypeDeclarationMaps = {\n interfaces: Map<string, TSESTree.TSInterfaceDeclaration>;\n typeAliases: Map<string, TSESTree.TSTypeAliasDeclaration>;\n};\n\ntype TypeCheckerContext = {\n checker: ts.TypeChecker;\n services: ReturnType<typeof ESLintUtils.getParserServices>;\n};\n\nconst componentWrapperNames = new Set([\"forwardRef\", \"memo\"]);\n\nconst publicEntrypointFileNames = [\"index.ts\", \"index.tsx\"];\n\ntype TypeSymbolInfo = {\n symbolName: string | undefined;\n declarations: Array<ts.Declaration>;\n};\n\nconst getTypeSymbolInfo = (type: ts.Type): TypeSymbolInfo => {\n try {\n return {\n symbolName: type.symbol.getName(),\n declarations: type.symbol.getDeclarations() ?? [],\n };\n } catch {\n return {\n symbolName: undefined,\n declarations: [],\n };\n }\n};\n\nconst getTypeReferenceName = (typeName: TSESTree.EntityName): string | null => {\n if (typeName.type === AST_NODE_TYPES.Identifier) {\n return typeName.name;\n }\n\n if (typeName.type === AST_NODE_TYPES.TSQualifiedName) {\n return typeName.right.name;\n }\n\n return null;\n};\n\nconst getCallExpressionName = (node: TSESTree.CallExpression): string | null => {\n const { callee } = node;\n\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name;\n }\n\n if (callee.type === AST_NODE_TYPES.MemberExpression && callee.property.type === AST_NODE_TYPES.Identifier) {\n return callee.property.name;\n }\n\n return null;\n};\n\nconst isPascalCaseName = (name: string): boolean => /^[A-Z]/.test(name);\n\nconst normalizeFilePath = (filePath: string): string => path.normalize(filePath);\n\nconst getProjectRoot = (projectJsonPath: string): string => path.dirname(projectJsonPath);\n\nconst getPublicEntrypointPaths = (projectRoot: string): Array<string> =>\n publicEntrypointFileNames.map(fileName => path.join(projectRoot, \"src\", fileName));\n\nconst getModulePathCandidates = (fromFilePath: string, moduleSpecifier: string): Array<string> => {\n const modulePath = path.resolve(path.dirname(fromFilePath), moduleSpecifier);\n\n return [\n modulePath,\n `${modulePath}.ts`,\n `${modulePath}.tsx`,\n path.join(modulePath, \"index.ts\"),\n path.join(modulePath, \"index.tsx\"),\n ];\n};\n\nconst moduleSpecifierTargetsFile = (fromFilePath: string, moduleSpecifier: string, targetFilePath: string): boolean => {\n if (!moduleSpecifier.startsWith(\".\")) {\n return false;\n }\n\n const normalizedTargetFilePath = normalizeFilePath(targetFilePath);\n return getModulePathCandidates(fromFilePath, moduleSpecifier).some(\n candidatePath => normalizeFilePath(candidatePath) === normalizedTargetFilePath\n );\n};\n\nconst getSourceExportName = (specifier: ts.ExportSpecifier): string => {\n if (specifier.propertyName?.text === \"default\") {\n return specifier.name.text;\n }\n\n return specifier.propertyName?.text ?? specifier.name.text;\n};\n\nconst getPublicExportedNamesForFile = (\n projectRoot: string,\n filePath: string\n): { exportsAll: boolean; names: Set<string> } => {\n const result = {\n exportsAll: false,\n names: new Set<string>(),\n };\n\n for (const entrypointPath of getPublicEntrypointPaths(projectRoot)) {\n let sourceText: string;\n try {\n sourceText = fs.readFileSync(entrypointPath, \"utf8\");\n } catch {\n continue;\n }\n\n const sourceFile = ts.createSourceFile(entrypointPath, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n\n for (const statement of sourceFile.statements) {\n if (!ts.isExportDeclaration(statement) || !statement.moduleSpecifier) {\n continue;\n }\n\n if (!ts.isStringLiteral(statement.moduleSpecifier)) {\n continue;\n }\n\n if (!moduleSpecifierTargetsFile(entrypointPath, statement.moduleSpecifier.text, filePath)) {\n continue;\n }\n\n if (!statement.exportClause) {\n result.exportsAll = true;\n continue;\n }\n\n if (ts.isNamedExports(statement.exportClause)) {\n statement.exportClause.elements.forEach(specifier => {\n result.names.add(getSourceExportName(specifier));\n });\n }\n }\n }\n\n return result;\n};\n\nconst isEntrypointFile = (projectRoot: string, filePath: string): boolean => {\n const normalizedFilePath = normalizeFilePath(filePath);\n return getPublicEntrypointPaths(projectRoot).some(\n entrypointPath => normalizeFilePath(entrypointPath) === normalizedFilePath\n );\n};\n\nconst isComponentWrapperCallExpression = (node: TSESTree.CallExpression): boolean => {\n const firstArgument = node.arguments[0];\n const callExpressionName = getCallExpressionName(node);\n\n if (!callExpressionName || !componentWrapperNames.has(callExpressionName)) {\n return false;\n }\n\n return (\n firstArgument?.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n firstArgument?.type === AST_NODE_TYPES.FunctionExpression\n );\n};\n\nconst getWrappedComponentFunction = (\n node: TSESTree.CallExpression\n): TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression | null => {\n if (!isComponentWrapperCallExpression(node)) {\n return null;\n }\n\n const firstArgument = node.arguments[0];\n return firstArgument &&\n (firstArgument.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n firstArgument.type === AST_NODE_TYPES.FunctionExpression)\n ? firstArgument\n : null;\n};\n\nconst getHeritageName = (heritage: TSESTree.TSInterfaceHeritage): string | null => {\n const { expression } = heritage;\n\n if (expression.type === AST_NODE_TYPES.Identifier) {\n return expression.name;\n }\n\n if (expression.type === AST_NODE_TYPES.MemberExpression && expression.property.type === AST_NODE_TYPES.Identifier) {\n return expression.property.name;\n }\n\n return null;\n};\n\nconst getParameterTypeAnnotation = (parameter: TSESTree.Parameter | undefined): TSESTree.TypeNode | null => {\n if (!parameter) {\n return null;\n }\n\n if (parameter.type === AST_NODE_TYPES.Identifier || parameter.type === AST_NODE_TYPES.ObjectPattern) {\n return parameter.typeAnnotation?.typeAnnotation ?? null;\n }\n\n if (parameter.type === AST_NODE_TYPES.AssignmentPattern) {\n const { left } = parameter;\n if (left.type === AST_NODE_TYPES.Identifier || left.type === AST_NODE_TYPES.ObjectPattern) {\n return left.typeAnnotation?.typeAnnotation ?? null;\n }\n }\n\n return null;\n};\n\nconst getFunctionPropsType = (\n node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression\n): TSESTree.TypeNode | null => getParameterTypeAnnotation(node.params[0]);\n\nconst getPropsTypeFromCallExpression = (node: TSESTree.CallExpression): TSESTree.TypeNode | null => {\n const typeArguments = node.typeArguments?.params ?? [];\n const firstArgument = node.arguments[0];\n\n if (\n firstArgument?.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n firstArgument?.type === AST_NODE_TYPES.FunctionExpression\n ) {\n const parameterType = getParameterTypeAnnotation(firstArgument.params[0]);\n if (parameterType) {\n return parameterType;\n }\n }\n\n if (getCallExpressionName(node) === \"forwardRef\") {\n return typeArguments[1] ?? null;\n }\n\n return typeArguments[0] ?? null;\n};\n\nconst getPropsTypeFromVariableDeclarator = (node: TSESTree.VariableDeclarator): TSESTree.TypeNode | null => {\n const { init } = node;\n\n if (!init) {\n return null;\n }\n\n if (init.type === AST_NODE_TYPES.ArrowFunctionExpression) {\n return getFunctionPropsType(init);\n }\n\n if (init.type === AST_NODE_TYPES.CallExpression) {\n return getPropsTypeFromCallExpression(init);\n }\n\n return null;\n};\n\nconst isExportedDeclaration = (node: TSESTree.Node): boolean => {\n const parent = node.parent;\n if (!parent) {\n return false;\n }\n\n if (\n parent.type === AST_NODE_TYPES.ExportNamedDeclaration ||\n parent.type === AST_NODE_TYPES.ExportDefaultDeclaration\n ) {\n return true;\n }\n\n const grandParent = parent.parent;\n return grandParent?.type === AST_NODE_TYPES.ExportNamedDeclaration;\n};\n\nconst typeHasRequiredInterface = (\n typeNode: TSESTree.TypeNode,\n requiredInterface: string,\n declarations: TypeDeclarationMaps,\n visitedTypeNames = new Set<string>()\n): boolean => {\n switch (typeNode.type) {\n case AST_NODE_TYPES.TSTypeReference: {\n const referenceName = getTypeReferenceName(typeNode.typeName);\n if (!referenceName) {\n return false;\n }\n\n if (referenceName === requiredInterface) {\n return true;\n }\n\n if (visitedTypeNames.has(referenceName)) {\n return false;\n }\n\n visitedTypeNames.add(referenceName);\n\n const interfaceDeclaration = declarations.interfaces.get(referenceName);\n if (interfaceDeclaration) {\n return interfaceExtendsRequiredInterface(\n interfaceDeclaration,\n requiredInterface,\n declarations,\n visitedTypeNames\n );\n }\n\n const typeAlias = declarations.typeAliases.get(referenceName);\n if (typeAlias) {\n return typeHasRequiredInterface(typeAlias.typeAnnotation, requiredInterface, declarations, visitedTypeNames);\n }\n\n return false;\n }\n\n case AST_NODE_TYPES.TSIntersectionType:\n return typeNode.types.some(part =>\n typeHasRequiredInterface(part, requiredInterface, declarations, new Set(visitedTypeNames))\n );\n\n case AST_NODE_TYPES.TSUnionType:\n return typeNode.types.every(part =>\n typeHasRequiredInterface(part, requiredInterface, declarations, new Set(visitedTypeNames))\n );\n\n default:\n return false;\n }\n};\n\nconst interfaceExtendsRequiredInterface = (\n declaration: TSESTree.TSInterfaceDeclaration,\n requiredInterface: string,\n declarations: TypeDeclarationMaps,\n visitedTypeNames: Set<string>\n): boolean => {\n return declaration.extends.some(heritage => {\n const heritageName = getHeritageName(heritage);\n if (!heritageName) {\n return false;\n }\n\n if (heritageName === requiredInterface) {\n return true;\n }\n\n if (visitedTypeNames.has(heritageName)) {\n return false;\n }\n\n visitedTypeNames.add(heritageName);\n\n const interfaceDeclaration = declarations.interfaces.get(heritageName);\n if (interfaceDeclaration) {\n return interfaceExtendsRequiredInterface(interfaceDeclaration, requiredInterface, declarations, visitedTypeNames);\n }\n\n const typeAlias = declarations.typeAliases.get(heritageName);\n if (typeAlias) {\n return typeHasRequiredInterface(typeAlias.typeAnnotation, requiredInterface, declarations, visitedTypeNames);\n }\n\n return false;\n });\n};\n\nconst interfaceHasRequiredProp = (\n declaration: TSESTree.TSInterfaceDeclaration,\n requiredProp: string,\n declarations: TypeDeclarationMaps,\n visitedTypeNames: Set<string>\n): boolean => {\n const hasOwnProp = declaration.body.body.some(member => {\n if (member.type !== AST_NODE_TYPES.TSPropertySignature) {\n return false;\n }\n\n return member.key.type === AST_NODE_TYPES.Identifier && member.key.name === requiredProp;\n });\n\n if (hasOwnProp) {\n return true;\n }\n\n return declaration.extends.some(heritage => {\n const heritageName = getHeritageName(heritage);\n if (!heritageName || visitedTypeNames.has(heritageName)) {\n return false;\n }\n\n visitedTypeNames.add(heritageName);\n\n const interfaceDeclaration = declarations.interfaces.get(heritageName);\n if (interfaceDeclaration) {\n return interfaceHasRequiredProp(interfaceDeclaration, requiredProp, declarations, visitedTypeNames);\n }\n\n const typeAlias = declarations.typeAliases.get(heritageName);\n if (typeAlias) {\n return typeHasRequiredProp(typeAlias.typeAnnotation, requiredProp, declarations, visitedTypeNames);\n }\n\n return false;\n });\n};\n\nconst typeLiteralHasRequiredProp = (typeNode: TSESTree.TSTypeLiteral, requiredProp: string): boolean => {\n return typeNode.members.some(member => {\n if (member.type !== AST_NODE_TYPES.TSPropertySignature) {\n return false;\n }\n\n return member.key.type === AST_NODE_TYPES.Identifier && member.key.name === requiredProp;\n });\n};\n\nconst typeHasRequiredProp = (\n typeNode: TSESTree.TypeNode,\n requiredProp: string,\n declarations: TypeDeclarationMaps,\n visitedTypeNames = new Set<string>()\n): boolean => {\n switch (typeNode.type) {\n case AST_NODE_TYPES.TSTypeLiteral:\n return typeLiteralHasRequiredProp(typeNode, requiredProp);\n\n case AST_NODE_TYPES.TSTypeReference: {\n const referenceName = getTypeReferenceName(typeNode.typeName);\n if (!referenceName || visitedTypeNames.has(referenceName)) {\n return false;\n }\n\n visitedTypeNames.add(referenceName);\n\n const interfaceDeclaration = declarations.interfaces.get(referenceName);\n if (interfaceDeclaration) {\n return interfaceHasRequiredProp(interfaceDeclaration, requiredProp, declarations, visitedTypeNames);\n }\n\n const typeAlias = declarations.typeAliases.get(referenceName);\n if (typeAlias) {\n return typeHasRequiredProp(typeAlias.typeAnnotation, requiredProp, declarations, visitedTypeNames);\n }\n\n return false;\n }\n\n case AST_NODE_TYPES.TSIntersectionType:\n return typeNode.types.some(part =>\n typeHasRequiredProp(part, requiredProp, declarations, new Set(visitedTypeNames))\n );\n\n case AST_NODE_TYPES.TSUnionType:\n return typeNode.types.every(part =>\n typeHasRequiredProp(part, requiredProp, declarations, new Set(visitedTypeNames))\n );\n\n default:\n return false;\n }\n};\n\nconst getTypeCheckerContext = (context: TSESLint.RuleContext<MessageIds, Options>): TypeCheckerContext | null => {\n try {\n const services = ESLintUtils.getParserServices(context);\n return {\n checker: services.program.getTypeChecker(),\n services,\n };\n } catch {\n return null;\n }\n};\n\nexport const checkerTypeHasRequiredInterface = (\n type: ts.Type,\n requiredInterface: string,\n checker: ts.TypeChecker,\n visitedTypeNames = new Set<string>()\n): boolean => {\n if (type.isUnion()) {\n return type.types.every(part => checkerTypeHasRequiredInterface(part, requiredInterface, checker, new Set()));\n }\n\n if (type.isIntersection()) {\n return type.types.some(part =>\n checkerTypeHasRequiredInterface(part, requiredInterface, checker, new Set(visitedTypeNames))\n );\n }\n\n const { symbolName, declarations } = getTypeSymbolInfo(type);\n const aliasSymbolName = type.aliasSymbol?.getName();\n\n if (symbolName === requiredInterface || aliasSymbolName === requiredInterface) {\n return true;\n }\n\n const visitKey = aliasSymbolName ?? symbolName;\n if (visitKey) {\n if (visitedTypeNames.has(visitKey)) {\n return false;\n }\n visitedTypeNames.add(visitKey);\n }\n\n if (\n type.aliasTypeArguments?.some(typeArgument =>\n checkerTypeHasRequiredInterface(typeArgument, requiredInterface, checker)\n )\n ) {\n return true;\n }\n\n if (type.isClassOrInterface()) {\n const baseTypes = checker.getBaseTypes(type);\n if (\n baseTypes.some(baseType =>\n checkerTypeHasRequiredInterface(baseType, requiredInterface, checker, visitedTypeNames)\n )\n ) {\n return true;\n }\n }\n\n return declarations.some(declaration => {\n if (!ts.isInterfaceDeclaration(declaration) || !declaration.heritageClauses) {\n return false;\n }\n\n return declaration.heritageClauses.some(heritageClause =>\n heritageClause.types.some(heritageType => {\n const heritageInterfaceType = checker.getTypeAtLocation(heritageType);\n return checkerTypeHasRequiredInterface(heritageInterfaceType, requiredInterface, checker, visitedTypeNames);\n })\n );\n });\n};\n\nconst checkerTypeHasRequiredProp = (type: ts.Type, requiredProp: string, checker: ts.TypeChecker): boolean => {\n if (type.isUnion()) {\n return type.types.every(part => checkerTypeHasRequiredProp(part, requiredProp, checker));\n }\n\n return Boolean(type.getProperty(requiredProp));\n};\n\nconst getCheckerType = (typeNode: TSESTree.TypeNode, typeCheckerContext: TypeCheckerContext | null): ts.Type | null => {\n if (!typeCheckerContext) {\n return null;\n }\n\n const tsNode = typeCheckerContext.services.esTreeNodeToTSNodeMap.get(typeNode);\n return typeCheckerContext.checker.getTypeAtLocation(tsNode);\n};\n\nexport const requireComponentPropContracts = createRule<Options, MessageIds>({\n name: \"require-component-prop-contracts\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Require exported React component props to include configured prop names or extend configured interfaces.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n requiredProps: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Prop names every exported component props type must include.\",\n },\n requiredInterfaces: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Interface names every exported component props type must reference or extend.\",\n },\n restrictToComponentsWithJsxReturn: {\n type: \"boolean\",\n description:\n \"When true, only enforce for components that return intrinsic JSX. Defaults to false (all components).\",\n },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n missingPropContracts:\n \"Public component '{{componentName}}' props must satisfy these contracts: {{missingContracts}}.\",\n },\n },\n defaultOptions: [\n {\n requiredProps: [],\n requiredInterfaces: [],\n restrictToComponentsWithJsxReturn: false,\n },\n ],\n create(context, [options]) {\n const filename = context.filename;\n if (!filename.endsWith(\".tsx\")) {\n return {};\n }\n\n const projectMetadata = getProjectMetadata(filename);\n if (!projectMetadata) {\n return {};\n }\n\n const requiredProps = options.requiredProps ?? [];\n const requiredInterfaces = options.requiredInterfaces ?? [];\n const restrictToComponentsWithJsxReturn = options.restrictToComponentsWithJsxReturn ?? false;\n if (requiredProps.length === 0 && requiredInterfaces.length === 0) {\n return {};\n }\n\n const declarations: TypeDeclarationMaps = {\n interfaces: new Map(),\n typeAliases: new Map(),\n };\n const typeCheckerContext = getTypeCheckerContext(context);\n const exportedIdentifiers = new Set<string>();\n const componentCandidates: Array<ComponentCandidate> = [];\n const projectRoot = getProjectRoot(projectMetadata.projectJsonPath);\n const publicExports = getPublicExportedNamesForFile(projectRoot, filename);\n const isCurrentFileEntrypoint = isEntrypointFile(projectRoot, filename);\n\n const isExportedComponentName = (componentName: string, node: TSESTree.Node): boolean => {\n if (\n !isPascalCaseName(componentName) ||\n (!isExportedDeclaration(node) && !exportedIdentifiers.has(componentName))\n ) {\n return false;\n }\n\n return isCurrentFileEntrypoint || publicExports.exportsAll || publicExports.names.has(componentName);\n };\n\n const checkCandidate = (candidate: ComponentCandidate): void => {\n const checkerType = candidate.propsType ? getCheckerType(candidate.propsType, typeCheckerContext) : null;\n const missingProps = requiredProps.filter(\n requiredProp =>\n !candidate.propsType ||\n (checkerType && typeCheckerContext\n ? !checkerTypeHasRequiredProp(checkerType, requiredProp, typeCheckerContext.checker)\n : !typeHasRequiredProp(candidate.propsType, requiredProp, declarations, new Set()))\n );\n const missingInterfaces = requiredInterfaces.filter(\n requiredInterface =>\n !candidate.propsType ||\n (checkerType && typeCheckerContext\n ? !checkerTypeHasRequiredInterface(checkerType, requiredInterface, typeCheckerContext.checker)\n : !typeHasRequiredInterface(candidate.propsType, requiredInterface, declarations, new Set()))\n );\n const missingContracts = [...missingProps, ...missingInterfaces];\n\n if (missingContracts.length === 0) {\n return;\n }\n\n context.report({\n node: candidate.node,\n messageId: \"missingPropContracts\",\n data: {\n componentName: candidate.componentName,\n missingContracts: missingContracts.join(\", \"),\n },\n });\n };\n\n return {\n ExportNamedDeclaration(node: TSESTree.ExportNamedDeclaration) {\n for (const specifier of node.specifiers) {\n if (specifier.local.type === AST_NODE_TYPES.Identifier) {\n exportedIdentifiers.add(specifier.local.name);\n }\n }\n },\n\n ExportDefaultDeclaration(node: TSESTree.ExportDefaultDeclaration) {\n if (node.declaration.type === AST_NODE_TYPES.Identifier) {\n exportedIdentifiers.add(node.declaration.name);\n }\n },\n\n TSInterfaceDeclaration(node: TSESTree.TSInterfaceDeclaration) {\n declarations.interfaces.set(node.id.name, node);\n },\n\n TSTypeAliasDeclaration(node: TSESTree.TSTypeAliasDeclaration) {\n declarations.typeAliases.set(node.id.name, node);\n },\n\n FunctionDeclaration(node: TSESTree.FunctionDeclaration) {\n const componentName = node.id?.name;\n const returnsIntrinsicJsx = functionReturnsIntrinsicJSX(node) === true;\n if (\n !componentName ||\n !isReactComponent(node) ||\n (restrictToComponentsWithJsxReturn && !returnsIntrinsicJsx) ||\n !isExportedComponentName(componentName, node)\n ) {\n return;\n }\n\n componentCandidates.push({\n componentName,\n node,\n propsType: getFunctionPropsType(node),\n });\n },\n\n VariableDeclarator(node: TSESTree.VariableDeclarator) {\n if (node.id.type !== AST_NODE_TYPES.Identifier) {\n return;\n }\n\n const { init } = node;\n const wrappedComponentFunction =\n init?.type === AST_NODE_TYPES.CallExpression ? getWrappedComponentFunction(init) : null;\n const isComponent =\n init?.type === AST_NODE_TYPES.ArrowFunctionExpression\n ? isReactComponent(init)\n : wrappedComponentFunction !== null;\n const returnsJsx =\n init?.type === AST_NODE_TYPES.ArrowFunctionExpression\n ? functionReturnsIntrinsicJSX(init) === true\n : wrappedComponentFunction !== null && functionReturnsIntrinsicJSX(wrappedComponentFunction) === true;\n\n if (\n !isComponent ||\n (restrictToComponentsWithJsxReturn && !returnsJsx) ||\n !isExportedComponentName(node.id.name, node)\n ) {\n return;\n }\n\n componentCandidates.push({\n componentName: node.id.name,\n node,\n propsType: getPropsTypeFromVariableDeclarator(node),\n });\n },\n\n \"Program:exit\"() {\n componentCandidates.forEach(checkCandidate);\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"require-list-item-virtualization-props.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/require-list-item-virtualization-props/require-list-item-virtualization-props.ts"],"names":[],"mappings":"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","sourcesContent":["import { AST_NODE_TYPES, ESLintUtils, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}.ts`\n);\n\ntype Options = [\n {\n /**\n * Whether to allow custom components that extend VirtualizationListItemProps\n * instead of requiring explicit spreading of listItemProps\n */\n allowCustomComponents?: boolean;\n },\n];\n\ntype MessageIds = \"requireVirtualizationProps\" | \"spreadListItemProps\" | \"useSemanticListItem\";\n\n/**\n * Check if a spread attribute argument contains listItemProps\n */\nconst isListItemPropsSpread = (argument: TSESTree.Expression): boolean => {\n // Direct identifier: {...listItemProps}\n if (argument.type === AST_NODE_TYPES.Identifier) {\n return argument.name === \"listItemProps\" || argument.name.includes(\"ItemProps\");\n }\n\n // Member expression: {...params.listItemProps}\n if (argument.type === AST_NODE_TYPES.MemberExpression) {\n // Check if property is an identifier (not computed like params[\"listItemProps\"])\n if (!argument.computed && argument.property.type === AST_NODE_TYPES.Identifier) {\n const propertyName = argument.property.name;\n if (propertyName === \"listItemProps\" || propertyName.includes(\"ItemProps\")) {\n return true;\n }\n }\n }\n\n return false;\n};\n\n/**\n * Check if a JSX element has the required virtualization props\n */\nconst hasRequiredVirtualizationProps = (\n element: TSESTree.JSXElement,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): boolean => {\n // ref is functionally required for virtualization even though TypeScript marks it optional\n const requiredProps = [\"className\", \"data-index\", \"tabIndex\", \"ref\"];\n\n const attributes = element.openingElement.attributes;\n const propNames = new Set<string>();\n let hasSpreadListItemProps = false;\n\n for (const attr of attributes) {\n if (attr.type === AST_NODE_TYPES.JSXAttribute && attr.name.type === AST_NODE_TYPES.JSXIdentifier) {\n propNames.add(attr.name.name);\n } else if (attr.type === AST_NODE_TYPES.JSXSpreadAttribute) {\n // Check if spreading listItemProps or similar\n if (isListItemPropsSpread(attr.argument)) {\n hasSpreadListItemProps = true;\n } else {\n // Fallback: check source code text for listItemProps\n // This handles edge cases where AST structure might be different\n const sourceCode = context.sourceCode.getText(attr.argument);\n const hasListItemProps = sourceCode.includes(\"listItemProps\");\n const hasItemProps = sourceCode.includes(\"ItemProps\");\n if (hasListItemProps || hasItemProps) {\n hasSpreadListItemProps = true;\n }\n }\n }\n }\n\n // If spreading listItemProps, assume it has all required props\n if (hasSpreadListItemProps) {\n return true;\n }\n\n // Check if all required props are present\n return requiredProps.every(prop => propNames.has(prop));\n};\n\n/**\n * Check if we're inside a List component's render function\n */\nconst isInsideListRenderFunction = (node: TSESTree.Node): boolean => {\n let current: TSESTree.Node | undefined = node.parent;\n\n while (current) {\n // Look for JSX element named \"List\"\n if (\n current.type === AST_NODE_TYPES.JSXElement &&\n current.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier &&\n current.openingElement.name.name === \"List\"\n ) {\n return true;\n }\n current = current.parent;\n }\n\n return false;\n};\n\n/**\n * Check if a JSX element is a direct list item (directly returned from List render function)\n */\nconst isListItemElement = (element: TSESTree.JSXElement): boolean => {\n // Check if this element is the direct return value from a List render function\n const current: TSESTree.Node | undefined = element.parent;\n\n // We need to find if this element is DIRECTLY returned from the render function\n // This means it should be the immediate child of a return statement or arrow function body\n\n // Case 1: Direct return statement - return (<li>...</li>)\n if (current.type === AST_NODE_TYPES.ReturnStatement) {\n return isInsideListRenderFunction(current);\n }\n\n // Case 2: Arrow function body - ({ key, listItemProps, item }) => (<li>...</li>)\n if (current.type === AST_NODE_TYPES.ArrowFunctionExpression) {\n return isInsideListRenderFunction(current);\n }\n\n // Case 3: Conditional expression - item ? <li>...</li> : null\n if (current.type === AST_NODE_TYPES.ConditionalExpression) {\n // Check if the conditional is directly returned or is the arrow function body\n const conditionalParent = current.parent;\n if (\n conditionalParent.type === AST_NODE_TYPES.ReturnStatement ||\n conditionalParent.type === AST_NODE_TYPES.ArrowFunctionExpression\n ) {\n return isInsideListRenderFunction(conditionalParent);\n }\n }\n\n return false;\n};\n\n/**\n * Get the name of a JSX element\n */\nconst getJSXElementName = (element: TSESTree.JSXElement): string | null => {\n if (element.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier) {\n return element.openingElement.name.name;\n }\n return null;\n};\n\n/**\n * Check if element is a semantic list item element\n */\nconst isSemanticListItem = (elementName: string): boolean => {\n return elementName.toLowerCase() === \"li\";\n};\n\n/**\n * Check if element name is a built-in HTML element (vs custom React component)\n */\nconst isHTMLElement = (elementName: string): boolean => {\n // HTML elements are lowercase, React components start with uppercase\n if (elementName.length === 0) {\n return false;\n }\n const firstChar = elementName[0];\n if (!firstChar) {\n return false;\n }\n return firstChar === firstChar.toLowerCase();\n};\n\nexport const requireListItemVirtualizationProps = createRule<Options, MessageIds>({\n name: \"require-list-item-virtualization-props\",\n meta: {\n type: \"problem\",\n docs: {\n description: \"Require list items within <List> to have VirtualizationListItemProps\",\n },\n hasSuggestions: true,\n schema: [\n {\n type: \"object\",\n properties: {\n allowCustomComponents: { type: \"boolean\" },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n requireVirtualizationProps:\n \"List item '{{elementName}}' must include VirtualizationListItemProps. \" +\n \"Spread {...listItemProps} or manually specify className, data-index, tabIndex, ref props.\",\n spreadListItemProps: \"Spread {...listItemProps} on this element\",\n useSemanticListItem:\n \"Use semantic <li> elements for list items instead of '{{elementName}}'. \" +\n \"List items should be <li> elements with proper VirtualizationListItemProps.\",\n },\n },\n defaultOptions: [\n {\n allowCustomComponents: true,\n },\n ],\n create(context, options) {\n const config = options[0];\n\n return {\n JSXElement(node: TSESTree.JSXElement) {\n // Skip if not inside a List render function\n if (!isListItemElement(node)) {\n return;\n }\n\n const elementName = getJSXElementName(node);\n if (!elementName) {\n return;\n }\n\n // Check element type and apply appropriate rules\n if (isHTMLElement(elementName)) {\n // For HTML elements, enforce semantic list items\n if (!isSemanticListItem(elementName)) {\n context.report({\n node: node.openingElement,\n messageId: \"useSemanticListItem\",\n data: { elementName },\n });\n return;\n }\n\n // For <li> elements, require virtualization props\n if (!hasRequiredVirtualizationProps(node, context)) {\n context.report({\n node: node.openingElement,\n messageId: \"requireVirtualizationProps\",\n data: { elementName },\n suggest: [\n {\n messageId: \"spreadListItemProps\",\n fix(fixer) {\n // Add {...listItemProps} as the first attribute\n const openingTag = node.openingElement;\n const firstAttr = openingTag.attributes[0];\n\n if (firstAttr) {\n return fixer.insertTextBefore(firstAttr, \"{...listItemProps} \");\n } else {\n // Insert after the element name\n return fixer.insertTextAfter(openingTag.name, \" {...listItemProps}\");\n }\n },\n },\n ],\n });\n }\n } else {\n // For custom components, check allowCustomComponents setting\n if (config.allowCustomComponents === false && !hasRequiredVirtualizationProps(node, context)) {\n context.report({\n node: node.openingElement,\n messageId: \"requireVirtualizationProps\",\n data: { elementName },\n suggest: [\n {\n messageId: \"spreadListItemProps\",\n fix(fixer) {\n // Add {...listItemProps} as the first attribute\n const openingTag = node.openingElement;\n const firstAttr = openingTag.attributes[0];\n\n if (firstAttr) {\n return fixer.insertTextBefore(firstAttr, \"{...listItemProps} \");\n } else {\n // Insert after the element name\n return fixer.insertTextAfter(openingTag.name, \" {...listItemProps}\");\n }\n },\n },\n ],\n });\n }\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"require-optional-prop-initialization.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/require-optional-prop-initialization/require-optional-prop-initialization.ts"],"names":[],"mappings":"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","sourcesContent":["import { AST_NODE_TYPES, ESLintUtils, TSESTree } from \"@typescript-eslint/utils\";\nimport {\n hasExistingBodyInitializations,\n isParameterExplicitlyDestructured,\n isParameterInitialized,\n isParameterOnlyUsedInJSX,\n isParameterUsedInFunction,\n isReactComponent,\n} from \"../../utils/ast-utils\";\nimport { getOptionalPropsFromType } from \"../../utils/typescript-utils\";\nimport { generateSuggestions, type MessageIds } from \"./suggestion-utils\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}.ts`\n);\n\ntype Options = [\n {\n allowNullableObject?: boolean;\n allowNullableBoolean?: boolean;\n allowNullableString?: boolean;\n allowNullableNumber?: boolean;\n allowNullableEnum?: boolean;\n allowNullableStringLiteralUnion?: boolean;\n onlyRequireUsedProps?: boolean;\n },\n];\n\nexport const requireOptionalPropInitialization = createRule<Options, MessageIds>({\n name: \"require-optional-prop-initialization\",\n meta: {\n type: \"suggestion\",\n docs: {\n description: \"Require optional component props to be initialized inside the component\",\n },\n hasSuggestions: true,\n schema: [\n {\n type: \"object\",\n properties: {\n allowNullableObject: { type: \"boolean\" },\n allowNullableBoolean: { type: \"boolean\" },\n allowNullableString: { type: \"boolean\" },\n allowNullableNumber: { type: \"boolean\" },\n allowNullableEnum: { type: \"boolean\" },\n allowNullableStringLiteralUnion: { type: \"boolean\" },\n onlyRequireUsedProps: { type: \"boolean\" },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n requireInitialization: \"Optional prop '{{propName}}' should be initialized\",\n initializeProp: \"{{description}}\",\n },\n },\n defaultOptions: [\n {\n allowNullableObject: true,\n allowNullableBoolean: false,\n allowNullableString: true,\n allowNullableNumber: true,\n allowNullableEnum: false,\n allowNullableStringLiteralUnion: false,\n onlyRequireUsedProps: true,\n },\n ],\n create(context, options) {\n const config = options[0];\n\n // Helper function to check component props\n const checkComponentProps = (\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n propsParam: TSESTree.Parameter | undefined\n ) => {\n if (!propsParam) {\n return;\n }\n\n let typeAnnotation: TSESTree.TypeNode | undefined;\n\n // Handle both regular parameters (props: Props) and destructured parameters ({prop1, prop2}: Props)\n if (propsParam.type === AST_NODE_TYPES.Identifier || propsParam.type === AST_NODE_TYPES.ObjectPattern) {\n typeAnnotation = propsParam.typeAnnotation?.typeAnnotation;\n } else {\n return;\n }\n\n const optionalProps = getOptionalPropsFromType(context, typeAnnotation);\n\n if (optionalProps.length === 0) {\n return;\n }\n\n const functionBody = functionNode.body.type === AST_NODE_TYPES.BlockStatement ? functionNode.body.body : [];\n\n optionalProps.forEach(prop => {\n // Check if this prop type is allowed to be nullable based on configuration\n const isAllowed =\n (prop.type === \"object\" && config.allowNullableObject === true) ||\n (prop.type === \"boolean\" && config.allowNullableBoolean === true) ||\n (prop.type === \"string\" && config.allowNullableString === true) ||\n (prop.type === \"number\" && config.allowNullableNumber === true) ||\n (prop.type === \"enum\" && config.allowNullableEnum === true) ||\n (prop.type === \"stringLiteral\" && config.allowNullableStringLiteralUnion === true) ||\n prop.type === \"unknown\"; // Always allow unknown types\n\n if (isAllowed) {\n return;\n }\n\n // If onlyRequireUsedProps is enabled, skip unused props\n if (config.onlyRequireUsedProps === true && !isParameterUsedInFunction(context, functionNode, prop.name)) {\n return;\n }\n\n // Skip props that are not explicitly destructured (i.e., captured in rest parameters like ...restOptions)\n // and are not used in the component body - these are just being passed through\n if (\n !isParameterExplicitlyDestructured(propsParam, prop.name) &&\n !isParameterUsedInFunction(context, functionNode, prop.name)\n ) {\n return;\n }\n\n // Skip props that are only used for pass-through to child components (e.g., <Tag color={tagColor} />)\n if (isParameterOnlyUsedInJSX(context, functionNode, prop.name) === true) {\n return;\n }\n\n // Check if the prop is initialized in the function body or parameter defaults\n if (!isParameterInitialized(functionBody, prop.name, propsParam)) {\n const isDestructuredParam = propsParam.type === AST_NODE_TYPES.ObjectPattern;\n const hasBodyInits = hasExistingBodyInitializations(functionBody);\n const propsParamName = propsParam.type === AST_NODE_TYPES.Identifier ? propsParam.name : \"props\";\n\n const suggestions = generateSuggestions(\n prop,\n propsParamName,\n functionNode,\n isDestructuredParam,\n hasBodyInits,\n propsParam,\n context\n );\n\n // Find the specific property node for more precise reporting\n let reportNode: TSESTree.Node = propsParam;\n if (propsParam.type === AST_NODE_TYPES.ObjectPattern) {\n const propProperty = propsParam.properties.find(\n p =>\n p.type === AST_NODE_TYPES.Property &&\n p.key.type === AST_NODE_TYPES.Identifier &&\n p.key.name === prop.name\n );\n if (propProperty && propProperty.type === AST_NODE_TYPES.Property) {\n reportNode = propProperty;\n }\n }\n\n context.report({\n node: reportNode,\n messageId: \"requireInitialization\",\n data: { propName: prop.name },\n suggest: suggestions,\n });\n }\n });\n };\n\n return {\n FunctionDeclaration(node: TSESTree.FunctionDeclaration) {\n if (isReactComponent(node)) {\n checkComponentProps(node, node.params[0]);\n }\n },\n\n ArrowFunctionExpression(node: TSESTree.ArrowFunctionExpression) {\n if (isReactComponent(node)) {\n checkComponentProps(node, node.params[0]);\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"suggestion-utils.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/require-optional-prop-initialization/suggestion-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { AST_NODE_TYPES, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\nimport { isParameterExplicitlyDestructured } from \"../../utils/ast-utils\";\nimport { OptionalProp } from \"../../utils/typescript-utils\";\n\nexport type MessageIds = \"requireInitialization\" | \"initializeProp\";\n\nexport type SuggestionResult = {\n messageId: MessageIds;\n data?: Record<string, unknown>;\n fix: (fixer: TSESLint.RuleFixer) => TSESLint.RuleFix | Array<TSESLint.RuleFix> | null;\n};\n\n/**\n * Helper to find and replace a property in destructuring pattern\n */\nconst createParameterInitializationFix = (propName: string, value: string, propsParam: TSESTree.Parameter) => {\n return (fixer: TSESLint.RuleFixer) => {\n if (propsParam.type === AST_NODE_TYPES.ObjectPattern) {\n const property = propsParam.properties.find(\n p => p.type === AST_NODE_TYPES.Property && p.key.type === AST_NODE_TYPES.Identifier && p.key.name === propName\n );\n if (property && property.type === AST_NODE_TYPES.Property) {\n return fixer.replaceText(property, `${propName} = ${value}`);\n }\n }\n return null;\n };\n};\n\n/**\n * Helper to create body initialization fix\n */\nconst createBodyInitializationFix = (\n propName: string,\n value: string,\n propsParamName: string,\n functionBodyStart: number\n) => {\n return (fixer: TSESLint.RuleFixer) => {\n const destructuringFix = `\\n const { ${propName} = ${value} } = ${propsParamName};`;\n return fixer.insertTextAfterRange([functionBodyStart, functionBodyStart + 1], destructuringFix);\n };\n};\n\n/**\n * Helper to create a suggestion for a specific value\n */\nconst createSuggestion = (\n propName: string,\n value: string,\n displayValue: string,\n shouldUseParameterInit: boolean,\n propsParam: TSESTree.Parameter,\n propsParamName: string,\n functionBodyStart: number\n): SuggestionResult => {\n let locationSuffix = \"\";\n let fixFunction: (fixer: TSESLint.RuleFixer) => TSESLint.RuleFix | Array<TSESLint.RuleFix> | null;\n\n if (shouldUseParameterInit) {\n locationSuffix = \" in parameter\";\n fixFunction = createParameterInitializationFix(propName, value, propsParam);\n } else {\n fixFunction = createBodyInitializationFix(propName, value, propsParamName, functionBodyStart);\n }\n\n return {\n messageId: \"initializeProp\",\n data: { description: `Initialize '${propName}' to → ${displayValue}${locationSuffix}` },\n fix: fixFunction,\n };\n};\n\n/**\n * Helper to create suggestions for a set of values\n */\nconst createSuggestionsForValues = (\n propName: string,\n values: Array<{ value: string; display: string }>,\n shouldUseParameterInit: boolean,\n propsParam: TSESTree.Parameter,\n propsParamName: string,\n functionBodyStart: number\n): Array<SuggestionResult> => {\n return values.map(({ value, display }) =>\n createSuggestion(propName, value, display, shouldUseParameterInit, propsParam, propsParamName, functionBodyStart)\n );\n};\n\n/**\n * Helper function to generate suggestions for prop initialization\n */\nexport const generateSuggestions = (\n prop: OptionalProp,\n propsParamName: string,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n isDestructuredParam: boolean,\n hasBodyInits: boolean,\n propsParam: TSESTree.Parameter,\n _context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): Array<SuggestionResult> => {\n const suggestions: Array<SuggestionResult> = [];\n\n if (functionNode.body.type !== AST_NODE_TYPES.BlockStatement) {\n return suggestions; // Can't suggest for arrow functions without block body\n }\n\n // Don't offer suggestions for props captured in rest parameters (e.g., ...rest)\n // The developer should manually handle extracting these from the rest object\n if (!isParameterExplicitlyDestructured(propsParam, prop.name)) {\n return suggestions;\n }\n\n const functionBodyStart = functionNode.body.range[0];\n const MAX_SUGGESTIONS = 5; // Don't overwhelm with too many suggestions\n\n // Decide where to place the initialization:\n // Since we know the prop is explicitly destructured (early return above handles rest params),\n // we can choose between parameter initialization or body initialization\n const isAlreadyInParameterDestructuring =\n isDestructuredParam &&\n propsParam.type === AST_NODE_TYPES.ObjectPattern &&\n propsParam.properties.some(\n p => p.type === AST_NODE_TYPES.Property && p.key.type === AST_NODE_TYPES.Identifier && p.key.name === prop.name\n );\n\n const shouldUseParameterInit = isAlreadyInParameterDestructuring || (isDestructuredParam && !hasBodyInits);\n\n // Boolean suggestions: true, false, and undefined\n if (prop.type === \"boolean\") {\n const booleanValues = [\n { value: \"true\", display: \"true\" },\n { value: \"false\", display: \"false\" },\n { value: \"undefined\", display: \"undefined\" },\n ];\n suggestions.push(\n ...createSuggestionsForValues(\n prop.name,\n booleanValues,\n shouldUseParameterInit,\n propsParam,\n propsParamName,\n functionBodyStart\n )\n );\n }\n\n // String literal suggestions: each individual literal (if not too many)\n if (prop.type === \"stringLiteral\" && prop.stringLiterals.length <= MAX_SUGGESTIONS) {\n const stringLiteralValues = [\n ...prop.stringLiterals.map(literal => ({ value: `\"${literal}\"`, display: `\"${literal}\"` })),\n { value: \"undefined\", display: \"undefined\" },\n ];\n suggestions.push(\n ...createSuggestionsForValues(\n prop.name,\n stringLiteralValues,\n shouldUseParameterInit,\n propsParam,\n propsParamName,\n functionBodyStart\n )\n );\n }\n\n // Enum suggestions: each individual enum value (if not too many)\n if (prop.type === \"enum\" && prop.enumValues.length <= MAX_SUGGESTIONS) {\n const enumValues = [\n ...prop.enumValues.map(enumValue => {\n const valueStr = typeof enumValue === \"string\" ? `\"${enumValue}\"` : String(enumValue);\n return { value: valueStr, display: valueStr };\n }),\n { value: \"undefined\", display: \"undefined\" },\n ];\n suggestions.push(\n ...createSuggestionsForValues(\n prop.name,\n enumValues,\n shouldUseParameterInit,\n propsParam,\n propsParamName,\n functionBodyStart\n )\n );\n }\n\n // String type suggestions\n if (prop.type === \"string\") {\n const stringValues = [\n { value: '\"\"', display: '\"\"' },\n { value: \"undefined\", display: \"undefined\" },\n ];\n suggestions.push(\n ...createSuggestionsForValues(\n prop.name,\n stringValues,\n shouldUseParameterInit,\n propsParam,\n propsParamName,\n functionBodyStart\n )\n );\n }\n\n // Number type suggestions\n if (prop.type === \"number\") {\n const numberValues = [\n { value: \"0\", display: \"0\" },\n { value: \"undefined\", display: \"undefined\" },\n ];\n suggestions.push(\n ...createSuggestionsForValues(\n prop.name,\n numberValues,\n shouldUseParameterInit,\n propsParam,\n propsParamName,\n functionBodyStart\n )\n );\n }\n\n // Object/unknown type suggestions\n if (prop.type === \"object\" || prop.type === \"unknown\") {\n const typeDisplay = prop.type === \"unknown\" ? \"any value\" : prop.type;\n suggestions.push(\n createSuggestion(\n prop.name,\n \"undefined\",\n `undefined (${typeDisplay})`,\n shouldUseParameterInit,\n propsParam,\n propsParamName,\n functionBodyStart\n )\n );\n }\n\n return suggestions;\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"require-storybook-folder-landing-page.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/require-storybook-folder-landing-page/require-storybook-folder-landing-page.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Require a Storybook landing page (`*.docs.mdx` with `<Meta title=\"...\">`) for every ancestor\n * FOLDER implied by a story's title.\n *\n * Architecture: per-story-file rule. Each `*.stories.@(js|jsx|ts|tsx)` file declares a Storybook\n * `title` (e.g. \"Hooks/react-core-hooks/useDebounce\"). The folders implied by that title are the\n * accumulated path prefixes EXCLUDING the story leaf (here: \"Hooks\" and \"Hooks/react-core-hooks\").\n * Every such folder must have a landing page: a `*.docs.mdx` somewhere in the workspace whose\n * `<Meta title=\"FOLDER\" />` EXACTLY equals the folder path, with non-empty body and no TODO marker.\n *\n * The rule is REPORT-ONLY: it does not scaffold files. Creating a separate `*.docs.mdx` cannot be\n * expressed as a pure ESLint fix, and ESLint evaluates fix/suggestion callbacks on every lint pass\n * (not only under `--fix`), so a file-writing fix would write stubs during ordinary editor/CI lint.\n * Stub scaffolding is therefore delivered as a separate, explicit command (tracked as a follow-up).\n *\n * See README.md for incorrect/correct examples.\n */\n\nimport { AST_NODE_TYPES, ESLintUtils, TSESTree } from \"@typescript-eslint/utils\";\nimport * as crypto from \"crypto\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { findNearestFile } from \"../../utils/file-utils\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name =>\n `https://github.com/trackunit/manager/blob/master/libs/eslint/plugin-trackunit/src/lib/rules/${name}/${name}.ts`\n);\n\ntype MessageIds = \"missingLandingPage\";\ntype Options = [];\n\n/** Canonical TODO marker. A landing page still containing this marker does NOT satisfy the rule. */\nexport const STORYBOOK_LANDING_PAGE_TODO_MARKER = \"{/* TODO: storybook-folder-landing-page */}\";\n\n/**\n * Canonical permalink to the how-to-author doc. Single source of truth, embedded in the rule's\n * error message so developers tripping the rule get a direct link. The `master` permalink stays\n * stable across file moves within the (internal) repo.\n */\nexport const STORYBOOK_LANDING_PAGE_DOCS_URL =\n \"https://github.com/Trackunit/manager/blob/master/docs/STORYBOOK-LANDING-PAGES.md\";\n\n/** A discovered `*.docs.mdx` landing page keyed by its exact `<Meta title>`. */\ntype LandingPageEntry = {\n filePath: string;\n body: string;\n};\n\ntype LandingPageScan = {\n fingerprint: string;\n landingPages: Map<string, LandingPageEntry>;\n};\n\n/**\n * Cache of landing-page scans, keyed by workspace root. The cached value is reused only while the\n * current docs-file fingerprint matches, so long-lived ESLint processes pick up newly added or\n * edited landing pages without requiring an ESLint server restart.\n */\nconst landingPageCache = new Map<string, LandingPageScan>();\n\n/** Clear the module-level scan cache (primarily for tests). */\nexport const clearLandingPageCache = (): void => {\n landingPageCache.clear();\n};\n\nconst SKIP_DIRECTORIES = new Set([\"node_modules\", \"dist\", \".git\", \".nx\"]);\n\n// Match `title=\"...\"` anywhere within an opening `<Meta ...>` tag (attribute order independent).\nconst META_TITLE_REGEX = /<Meta\\b[^>]*?\\btitle\\s*=\\s*(\"|')(.*?)\\1/;\n\nconst STORY_FILE_REGEX = /\\.stories\\.(js|jsx|ts|tsx)$/;\nconst DOCS_MDX_REGEX = /\\.docs\\.mdx$/;\n\n/** Recursively collect absolute paths of every `*.docs.mdx` file under `dir`. */\nconst collectDocsMdxFiles = (dir: string): Array<string> => {\n const result: Array<string> = [];\n let entries: Array<fs.Dirent>;\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return result;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (!SKIP_DIRECTORIES.has(entry.name)) {\n result.push(...collectDocsMdxFiles(fullPath));\n }\n } else if (DOCS_MDX_REGEX.test(entry.name)) {\n result.push(fullPath);\n }\n }\n\n return result;\n};\n\n/** Strip import lines and the `<Meta .../>` tag, leaving the documentation body. */\nconst extractBody = (contents: string): string => {\n return contents\n .split(\"\\n\")\n .filter(line => !/^\\s*import\\s/.test(line))\n .join(\"\\n\")\n .replace(/<Meta\\b[^>]*\\/>/, \"\")\n .trim();\n};\n\n/** Scan the workspace for `*.docs.mdx` landing pages, building a title -> entry map. */\nconst scanLandingPages = (workspaceRoot: string): LandingPageScan => {\n const landingPages = new Map<string, LandingPageEntry>();\n const hash = crypto.createHash(\"sha256\");\n\n for (const filePath of collectDocsMdxFiles(workspaceRoot).toSorted()) {\n hash.update(filePath);\n hash.update(\"\\0\");\n\n let contents: string;\n try {\n contents = fs.readFileSync(filePath, \"utf-8\");\n } catch {\n hash.update(\"unreadable\");\n hash.update(\"\\0\");\n continue;\n }\n\n hash.update(contents);\n hash.update(\"\\0\");\n\n const match = META_TITLE_REGEX.exec(contents);\n if (match && typeof match[2] === \"string\") {\n landingPages.set(match[2], { filePath, body: extractBody(contents) });\n }\n }\n\n return { fingerprint: hash.digest(\"hex\"), landingPages };\n};\n\n/** Get landing pages from cache when the current docs-file fingerprint is unchanged. */\nconst getLandingPages = (workspaceRoot: string): Map<string, LandingPageEntry> => {\n const scan = scanLandingPages(workspaceRoot);\n const cached = landingPageCache.get(workspaceRoot);\n if (cached?.fingerprint === scan.fingerprint) {\n return cached.landingPages;\n }\n\n landingPageCache.set(workspaceRoot, scan);\n return scan.landingPages;\n};\n\n/** Derive ancestor folder paths from a title, dropping the story leaf. */\nconst deriveFolders = (title: string): Array<string> => {\n const segments = title.split(\"/\");\n const folders: Array<string> = [];\n // Drop the last segment (story leaf); accumulate prefixes for the rest.\n for (let i = 1; i < segments.length; i++) {\n folders.push(segments.slice(0, i).join(\"/\"));\n }\n return folders;\n};\n\n/** A folder is satisfied by a landing page entry with non-empty body and no TODO marker. */\nconst isSatisfied = (entry: LandingPageEntry | undefined): boolean => {\n if (!entry) {\n return false;\n }\n if (entry.body.length === 0) {\n return false;\n }\n return !entry.body.includes(STORYBOOK_LANDING_PAGE_TODO_MARKER);\n};\n\n/** Unwrap satisfies/as wrappers around an expression. */\nconst unwrapExpression = (node: TSESTree.Expression): TSESTree.Expression => {\n let current = node;\n while (current.type === AST_NODE_TYPES.TSSatisfiesExpression || current.type === AST_NODE_TYPES.TSAsExpression) {\n current = current.expression;\n }\n return current;\n};\n\n/** Extract a string-literal `title` property from an object expression, if present. */\nconst getTitleFromObject = (object: TSESTree.ObjectExpression): TSESTree.Literal | null => {\n for (const property of object.properties) {\n if (\n property.type === AST_NODE_TYPES.Property &&\n property.key.type === AST_NODE_TYPES.Identifier &&\n property.key.name === \"title\" &&\n property.value.type === AST_NODE_TYPES.Literal &&\n typeof property.value.value === \"string\"\n ) {\n return property.value;\n }\n }\n return null;\n};\n\nexport const requireStorybookFolderLandingPage = createRule<Options, MessageIds>({\n name: \"require-storybook-folder-landing-page\",\n meta: {\n type: \"problem\",\n docs: {\n description: \"Require a Storybook landing page (*.docs.mdx) for every ancestor folder implied by a story's title\",\n },\n schema: [],\n messages: {\n // URL embedded from the single-source-of-truth const (see STORYBOOK_LANDING_PAGE_DOCS_URL).\n missingLandingPage: `[require-storybook-folder-landing-page] Missing Storybook landing page for folder \"{{folder}}\". The <Meta title> must equal \"{{folder}}\" exactly (no extra leaf). Add a *.docs.mdx with <Meta title=\"{{folder}}\" /> and real content. See ${STORYBOOK_LANDING_PAGE_DOCS_URL} for how to author one.`,\n },\n },\n defaultOptions: [],\n create(context) {\n const currentFile = context.filename;\n\n // Only analyze story files (never .docs.* or .mdx).\n if (!STORY_FILE_REGEX.test(currentFile)) {\n return {};\n }\n\n const nxJsonPath = findNearestFile(currentFile, \"nx.json\");\n if (nxJsonPath === null) {\n return {};\n }\n const workspaceRoot = path.dirname(nxJsonPath);\n\n const reportForObject = (titleNode: TSESTree.Literal, reportNode: TSESTree.Node): void => {\n const title = titleNode.value;\n if (typeof title !== \"string\") {\n return;\n }\n\n const folders = deriveFolders(title);\n if (folders.length === 0) {\n return;\n }\n\n const landingPages = getLandingPages(workspaceRoot);\n\n for (const folder of folders) {\n const entry = landingPages.get(folder);\n if (isSatisfied(entry)) {\n continue;\n }\n\n context.report({\n node: reportNode,\n messageId: \"missingLandingPage\",\n data: { folder },\n });\n }\n };\n\n return {\n ExportDefaultDeclaration(node: TSESTree.ExportDefaultDeclaration) {\n const declaration = node.declaration;\n\n // Shape 1: export default { title: \"...\" }\n if (declaration.type === AST_NODE_TYPES.ObjectExpression) {\n const titleNode = getTitleFromObject(declaration);\n if (titleNode) {\n reportForObject(titleNode, node);\n }\n return;\n }\n\n // Shape 2: const meta = { title: \"...\" } satisfies Meta; export default meta;\n if (declaration.type === AST_NODE_TYPES.Identifier) {\n const variable = context.sourceCode\n .getScope(node)\n .references.find(ref => ref.identifier === declaration)?.resolved;\n const definition = variable?.defs[0];\n if (definition && definition.node.type === AST_NODE_TYPES.VariableDeclarator && definition.node.init) {\n const initializer = unwrapExpression(definition.node.init);\n if (initializer.type === AST_NODE_TYPES.ObjectExpression) {\n const titleNode = getTitleFromObject(initializer);\n if (titleNode) {\n reportForObject(titleNode, node);\n }\n }\n }\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"rules-map.js","sourceRoot":"","sources":["../../../../../../libs/eslint/plugin-trackunit/src/lib/rules-map.ts"],"names":[],"mappings":";;;AACA,6HAAuH;AACvH,6HAAqH;AACrH,qJAA6I;AAC7I,wGAAkG;AAClG,6KAAmK;AACnK,qJAA4I;AAC5I,+IAAmI;AACnI,qGAAgG;AAChG,kGAA4F;AAC5F,iHAA4G;AAC5G,+IAAwI;AACxI,qGAAgG;AAChG,2JAAkJ;AAClJ,0HAAqH;AACrH,gIAA0H;AAC1H,kJAA2I;AAC3I,4IAAsI;AACtI,+IAAwI;AAE3H,QAAA,QAAQ,GAAG;IACtB,iCAAiC,EAAE,8DAA4B;IAC/D,wBAAwB,EAAE,4CAAmB;IAC7C,iCAAiC,EAAE,4DAA0B;IAC7D,0BAA0B,EAAE,gDAAqB;IACjD,yBAAyB,EAAE,+CAAqB;IAChD,iDAAiD,EAAE,0FAAwC;IAC3F,yCAAyC,EAAE,4EAAkC;IAC7E,uCAAuC,EAAE,oEAA4B;IACrE,gCAAgC,EAAE,6DAA4B;IAC9D,yCAAyC,EAAE,2EAAiC;IAC5E,6BAA6B,EAAE,uDAAyB;IACxD,2CAA2C,EAAE,+EAAmC;IAChF,uCAAuC,EAAE,yEAAiC;IAC1E,sCAAsC,EAAE,wEAAiC;IACzE,kCAAkC,EAAE,gEAA6B;IACjE,yBAAyB,EAAE,+CAAqB;IAChD,wCAAwC,EAAE,2EAAkC;IAC5E,uCAAuC,EAAE,yEAAiC;CACM,CAAC","sourcesContent":["import { ESLintUtils } from \"@typescript-eslint/utils\";\nimport { componentNameMatchesFilename } from \"./rules/component-name-matches-filename/component-name-matches-filename\";\nimport { cvaMergeBaseClassesAsArray } from \"./rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array\";\nimport { designGuidelineButtonIconSizeMatch } from \"./rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match\";\nimport { noInternalBarrelFiles } from \"./rules/no-internal-barrel-files/no-internal-barrel-files\";\nimport { noInternalGraphqlWhenTaggedWithGqlPublic } from \"./rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public\";\nimport { noJestMockTrackunitReactCoreHooks } from \"./rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks\";\nimport { noTemplateStringsInClassName } from \"./rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop\";\nimport { noTypescriptAssertion } from \"./rules/no-typescript-assertion/no-typescript-assertion\";\nimport { oneComponentPerFile } from \"./rules/one-component-per-file/one-component-per-file\";\nimport { preferDestructuredImports } from \"./rules/prefer-destructured-imports/prefer-destructured-imports\";\nimport { preferEventSpecificCallbackNaming } from \"./rules/prefer-event-specific-callback-naming/prefer-event-specific-callback-naming\";\nimport { preferFieldComponents } from \"./rules/prefer-field-components/prefer-field-components\";\nimport { preferMouseEventHandlerInReactProps } from \"./rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props\";\nimport { requireClassnameAlternatives } from \"./rules/require-classname-alternatives/require-classname-alternatives\";\nimport { requireComponentPropContracts } from \"./rules/require-component-prop-contracts/require-component-prop-contracts\";\nimport { requireListItemVirtualizationProps } from \"./rules/require-list-item-virtualization-props/require-list-item-virtualization-props\";\nimport { requireOptionalPropInitialization } from \"./rules/require-optional-prop-initialization/require-optional-prop-initialization\";\nimport { requireStorybookFolderLandingPage } from \"./rules/require-storybook-folder-landing-page/require-storybook-folder-landing-page\";\n\nexport const rulesMap = {\n \"component-name-matches-filename\": componentNameMatchesFilename,\n \"one-component-per-file\": oneComponentPerFile,\n \"cva-merge-base-classes-as-array\": cvaMergeBaseClassesAsArray,\n \"no-internal-barrel-files\": noInternalBarrelFiles,\n \"no-typescript-assertion\": noTypescriptAssertion,\n \"no-internal-graphql-when-tagged-with-gql-public\": noInternalGraphqlWhenTaggedWithGqlPublic,\n \"design-guideline-button-icon-size-match\": designGuidelineButtonIconSizeMatch,\n \"no-template-strings-in-classname-prop\": noTemplateStringsInClassName,\n \"require-classname-alternatives\": requireClassnameAlternatives,\n \"no-jest-mock-trackunit-react-core-hooks\": noJestMockTrackunitReactCoreHooks,\n \"prefer-destructured-imports\": preferDestructuredImports,\n \"prefer-mouse-event-handler-in-react-props\": preferMouseEventHandlerInReactProps,\n \"prefer-event-specific-callback-naming\": preferEventSpecificCallbackNaming,\n \"require-optional-prop-initialization\": requireOptionalPropInitialization,\n \"require-component-prop-contracts\": requireComponentPropContracts,\n \"prefer-field-components\": preferFieldComponents,\n \"require-list-item-virtualization-props\": requireListItemVirtualizationProps,\n \"require-storybook-folder-landing-page\": requireStorybookFolderLandingPage,\n} satisfies Record<string, ESLintUtils.RuleModule<string, ReadonlyArray<unknown>>>;\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ast-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/ast-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { ASTUtils, AST_NODE_TYPES, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\n\n/**\n * Utility functions for analyzing AST nodes and function structure in ESLint rules.\n *\n * ## Core Utilities\n * - `isInParameterList()` - Check if a node is in a function's parameter list\n *\n * ## Parameter Analysis (Parameter → Usage)\n * - `isParameterExplicitlyDestructured()` - Check if parameter is explicitly destructured\n * - `isParameterInitialized()` - Check if parameter has a default value\n * - `isParameterUsedInFunction()` - Check if parameter is used in function body\n * - `hasExistingBodyInitializations()` - Check for initialization patterns in function body\n *\n * ## Identifier Origin Analysis (Usage → Origin)\n * - `getIdentifierParameterOrigin()` - Trace identifier back to see if it's from a parameter (rich return)\n * - `isIdentifierFromParameter()` - Boolean helper to check if identifier is from a parameter\n * - `isIdentifierFromRenderPropCallback()` - Check if identifier is from a render prop callback parameter\n *\n * ## JSX/React Specific\n * - `isReactComponent()` - Check if function is likely a React component\n * - `functionReturnsJSX()` - Check if function body returns JSX\n * - `functionReturnsIntrinsicJSX()` - Check if function body returns intrinsic JSX tags (e.g. `div`, `span`)\n * - `isParameterOnlyUsedInJSX()` - Check if parameter is only used in JSX attributes\n */\n\n/**\n * Helper function to check if a node is in the parameter list\n */\nconst isInParameterList = (\n node: TSESTree.Node,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression\n): boolean => {\n let current = node.parent;\n while (current) {\n // Check if current node is one of the function parameters\n const isParam = functionNode.params.some(param => param === current);\n if (isParam) {\n return true;\n }\n current = current.parent;\n }\n return false;\n};\n\n/**\n * Check if a parameter is explicitly destructured in the parameter list\n * (vs. captured in rest parameters like ...restOptions)\n */\nexport const isParameterExplicitlyDestructured = (parameter: TSESTree.Parameter, paramName: string): boolean => {\n if (parameter.type !== AST_NODE_TYPES.ObjectPattern) {\n return false;\n }\n\n // Check if the parameter is explicitly listed in the destructuring\n return parameter.properties.some(property => {\n if (property.type === AST_NODE_TYPES.Property && property.key.type === AST_NODE_TYPES.Identifier) {\n return property.key.name === paramName;\n }\n return false;\n });\n};\n\n/**\n * Check if there are any existing parameter initializations in the function body\n */\nexport const hasExistingBodyInitializations = (functionBody: Array<TSESTree.Statement>): boolean => {\n for (const stmt of functionBody) {\n // Check for destructuring with defaults: const { param = defaultValue } = params\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.ObjectPattern &&\n stmt.declarations[0].id.properties.some(\n prop => prop.type === AST_NODE_TYPES.Property && prop.value.type === AST_NODE_TYPES.AssignmentPattern\n )\n ) {\n return true;\n }\n\n // Check for variable declarations with defaults: const param = params.param ?? defaultValue\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].init?.type === AST_NODE_TYPES.LogicalExpression &&\n (stmt.declarations[0].init.operator === \"??\" || stmt.declarations[0].init.operator === \"||\")\n ) {\n return true;\n }\n }\n return false;\n};\n\n/**\n * Check if a parameter is initialized in the function body or parameter defaults\n */\nexport const isParameterInitialized = (\n functionBody: Array<TSESTree.Statement>,\n paramName: string,\n parameter?: TSESTree.Parameter\n): boolean => {\n // First check if the parameter has a default value in the parameter destructuring\n if (parameter && parameter.type === AST_NODE_TYPES.ObjectPattern) {\n for (const property of parameter.properties) {\n if (property.type === AST_NODE_TYPES.Property && property.value.type === AST_NODE_TYPES.AssignmentPattern) {\n // Handle both identifier keys (paramName) and string literal keys (\"param-name\")\n const keyName =\n property.key.type === AST_NODE_TYPES.Identifier\n ? property.key.name\n : property.key.type === AST_NODE_TYPES.Literal && typeof property.key.value === \"string\"\n ? property.key.value\n : null;\n\n if (keyName === paramName) {\n return true; // Found default value in parameter: {paramName = defaultValue}\n }\n }\n }\n }\n\n // Then check for initialization patterns in the function body\n for (const stmt of functionBody) {\n // Check for destructuring with defaults: const { param = defaultValue } = params\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.ObjectPattern\n ) {\n const pattern = stmt.declarations[0].id;\n for (const property of pattern.properties) {\n if (\n property.type === AST_NODE_TYPES.Property &&\n property.key.type === AST_NODE_TYPES.Identifier &&\n property.key.name === paramName &&\n property.value.type === AST_NODE_TYPES.AssignmentPattern\n ) {\n return true;\n }\n }\n }\n\n // Check for variable declarations with defaults: const param = params.param ?? defaultValue\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.Identifier &&\n stmt.declarations[0].id.name === paramName &&\n stmt.declarations[0].init?.type === AST_NODE_TYPES.LogicalExpression &&\n (stmt.declarations[0].init.operator === \"??\" || stmt.declarations[0].init.operator === \"||\")\n ) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * Check if a parameter is used within the function body\n */\nexport const isParameterUsedInFunction = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): boolean => {\n // Use TypeScript-ESLint's built-in findVariable utility for more robust variable detection\n const scope = context.sourceCode.getScope(functionNode);\n const variable = ASTUtils.findVariable(scope, paramName);\n\n if (variable) {\n // Check if the variable has any references (excluding the parameter definition)\n const references = variable.references.filter(ref => {\n // Exclude the parameter declaration itself\n const refNode = ref.identifier;\n return !isInParameterList(refNode, functionNode);\n });\n\n // Additional check: if the variable is only referenced in object literal shorthand property names\n // (like { placement: result.placement }), it's not actually using the parameter variable\n const actualUsageReferences = references.filter(ref => {\n const parent = ref.identifier.parent;\n\n // Skip if this is just a property key in an object literal\n // Example: { placement: result.placement } - the first 'placement' is just a key, not usage\n if (\n parent.type === AST_NODE_TYPES.Property &&\n parent.key === ref.identifier &&\n parent.value !== ref.identifier &&\n !parent.shorthand\n ) {\n return false;\n }\n\n return true;\n });\n\n if (actualUsageReferences.length > 0) {\n return true;\n }\n }\n\n // If direct variable reference not found, check for member access on rest parameters\n // e.g., rest.paramName, params.paramName, etc.\n const restParameters: Array<{ name: string; param: TSESTree.Parameter }> = [];\n\n // Look for rest elements in both direct params and inside object patterns\n functionNode.params.forEach(param => {\n if (param.type === AST_NODE_TYPES.RestElement && param.argument.type === AST_NODE_TYPES.Identifier) {\n // Direct rest parameter: (...rest: Params)\n restParameters.push({ name: param.argument.name, param });\n } else if (param.type === AST_NODE_TYPES.ObjectPattern) {\n // Look for rest elements inside object patterns: ({ param1, ...rest }: Params)\n param.properties.forEach(property => {\n if (property.type === AST_NODE_TYPES.RestElement && property.argument.type === AST_NODE_TYPES.Identifier) {\n restParameters.push({ name: property.argument.name, param });\n }\n });\n }\n });\n\n if (restParameters.length === 0) {\n return false;\n }\n\n // Check if the function body contains rest.paramName patterns\n const functionText = context.sourceCode.getText(functionNode);\n\n for (const restParam of restParameters) {\n const pattern = new RegExp(`\\\\b${restParam.name}\\\\.${paramName}\\\\b`);\n if (pattern.test(functionText)) {\n return true;\n }\n }\n\n return false;\n};\n\ntype FunctionLikeNode = TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression;\n\nconst jsxTagNameIsIntrinsic = (name: TSESTree.JSXTagNameExpression): boolean =>\n name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/.test(name.name);\n\nconst nodeContainsJSX = (node: TSESTree.Node): boolean => {\n if (node.type === AST_NODE_TYPES.JSXElement) {\n return true;\n }\n\n if (node.type === AST_NODE_TYPES.JSXFragment) {\n return true;\n }\n\n if (node.type === AST_NODE_TYPES.ConditionalExpression) {\n return nodeContainsJSX(node.consequent) || nodeContainsJSX(node.alternate);\n }\n\n if (node.type === AST_NODE_TYPES.LogicalExpression) {\n return nodeContainsJSX(node.left) || nodeContainsJSX(node.right);\n }\n\n return false;\n};\n\nconst nodeContainsIntrinsicJSX = (node: TSESTree.Node): boolean => {\n if (node.type === AST_NODE_TYPES.JSXElement) {\n if (jsxTagNameIsIntrinsic(node.openingElement.name)) {\n return true;\n }\n\n return node.children.some(child => {\n if (child.type === AST_NODE_TYPES.JSXElement || child.type === AST_NODE_TYPES.JSXFragment) {\n return nodeContainsIntrinsicJSX(child);\n }\n\n if (\n child.type === AST_NODE_TYPES.JSXExpressionContainer &&\n child.expression.type !== AST_NODE_TYPES.JSXEmptyExpression\n ) {\n return nodeContainsIntrinsicJSX(child.expression);\n }\n\n return false;\n });\n }\n\n if (node.type === AST_NODE_TYPES.JSXFragment) {\n return node.children.some(child => {\n if (child.type === AST_NODE_TYPES.JSXElement || child.type === AST_NODE_TYPES.JSXFragment) {\n return nodeContainsIntrinsicJSX(child);\n }\n\n if (\n child.type === AST_NODE_TYPES.JSXExpressionContainer &&\n child.expression.type !== AST_NODE_TYPES.JSXEmptyExpression\n ) {\n return nodeContainsIntrinsicJSX(child.expression);\n }\n\n return false;\n });\n }\n\n if (node.type === AST_NODE_TYPES.ConditionalExpression) {\n return nodeContainsIntrinsicJSX(node.consequent) || nodeContainsIntrinsicJSX(node.alternate);\n }\n\n if (node.type === AST_NODE_TYPES.LogicalExpression) {\n return nodeContainsIntrinsicJSX(node.left) || nodeContainsIntrinsicJSX(node.right);\n }\n\n return false;\n};\n\nexport const functionReturnsJSX = (node: FunctionLikeNode): boolean => {\n if (node.body.type === AST_NODE_TYPES.BlockStatement) {\n return node.body.body.some(\n statement =>\n statement.type === AST_NODE_TYPES.ReturnStatement &&\n statement.argument !== null &&\n nodeContainsJSX(statement.argument)\n );\n }\n\n return nodeContainsJSX(node.body);\n};\n\nexport const functionReturnsIntrinsicJSX = (node: FunctionLikeNode): boolean => {\n if (node.body.type === AST_NODE_TYPES.BlockStatement) {\n return node.body.body.some(\n statement =>\n statement.type === AST_NODE_TYPES.ReturnStatement &&\n statement.argument !== null &&\n nodeContainsIntrinsicJSX(statement.argument)\n );\n }\n\n return nodeContainsIntrinsicJSX(node.body);\n};\n\n/**\n * Check if a function is likely a React component based on naming and JSX usage\n */\nexport const isReactComponent = (node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression): boolean => {\n // Check if function name starts with uppercase (React convention)\n const functionName = node.type === AST_NODE_TYPES.FunctionDeclaration ? node.id?.name : null;\n const startsWithUppercase = /^[A-Z]/;\n if (functionName && startsWithUppercase.test(functionName)) {\n return true;\n }\n\n return functionReturnsJSX(node);\n};\n\n/**\n * Check if a parameter is only used in JSX attributes (pass-through to child components)\n * and nowhere else in the function body\n */\nexport const isParameterOnlyUsedInJSX = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): boolean => {\n // Use TypeScript-ESLint's built-in findVariable utility for robust variable detection\n const scope = context.sourceCode.getScope(functionNode);\n const variable = ASTUtils.findVariable(scope, paramName);\n\n if (!variable) {\n return false;\n }\n\n // Get all references to the parameter (excluding the parameter definition)\n const references = variable.references.filter(ref => {\n const refNode = ref.identifier;\n return !isInParameterList(refNode, functionNode);\n });\n\n if (references.length === 0) {\n return false;\n }\n\n // Check if all references are only in JSX attribute expressions\n const allReferencesAreJSXAttributes = references.every(ref => {\n const identifier = ref.identifier;\n let current = identifier.parent;\n\n // Walk up the AST to find if this identifier is used in a JSX attribute\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, @typescript-eslint/strict-boolean-expressions\n while (current) {\n // Check if we're in a JSX attribute expression: <Component prop={value} />\n if (current.type === AST_NODE_TYPES.JSXExpressionContainer) {\n const jsxParent = current.parent;\n if (jsxParent.type === AST_NODE_TYPES.JSXAttribute) {\n return true;\n }\n }\n\n // Check if we're in a JSX spread attribute: <Component {...props} />\n if (current.type === AST_NODE_TYPES.JSXSpreadAttribute) {\n return true;\n }\n\n // Allow dependency arrays for React hooks (useEffect, useMemo, useCallback, etc.)\n // These are acceptable for pass-through props since they're tracking the JSX usage\n if (current.type === AST_NODE_TYPES.ArrayExpression) {\n const callParent = current.parent;\n if (\n callParent.type === AST_NODE_TYPES.CallExpression &&\n callParent.callee.type === AST_NODE_TYPES.Identifier &&\n (callParent.callee.name.startsWith(\"use\") ||\n callParent.callee.name === \"useMemo\" ||\n callParent.callee.name === \"useCallback\" ||\n callParent.callee.name === \"useEffect\")\n ) {\n return true; // Allow dependency array usage\n }\n }\n\n // Stop if we reach certain node types that indicate we're not in JSX context\n if (\n current.type === AST_NODE_TYPES.VariableDeclarator ||\n current.type === AST_NODE_TYPES.AssignmentExpression ||\n current.type === AST_NODE_TYPES.CallExpression ||\n current.type === AST_NODE_TYPES.LogicalExpression ||\n current.type === AST_NODE_TYPES.ConditionalExpression ||\n current.type === AST_NODE_TYPES.BinaryExpression\n ) {\n return false;\n }\n\n if (!current.parent) {\n break;\n }\n current = current.parent;\n }\n\n return false;\n });\n\n return allReferencesAreJSXAttributes;\n};\n\n// ============================================================\n// Identifier Origin Analysis (traces usage back to definition)\n// ============================================================\n\n/**\n * Result of tracing an identifier back to its origin.\n * Used to distinguish between different ways an identifier can come from a function parameter.\n */\nexport type ParameterOriginResult =\n | {\n isFromParameter: true;\n /**\n * How the identifier relates to the parameter:\n * - \"direct-parameter\": Direct parameter, e.g., `(onClose) => ...`\n * - \"destructured-in-signature\": Destructured in function signature, e.g., `({ onClose }) => ...`\n * - \"destructured-in-body\": Destructured in function body, e.g., `const { onClose } = props`\n */\n originType: \"direct-parameter\" | \"destructured-in-signature\" | \"destructured-in-body\";\n }\n | { isFromParameter: false };\n\n/**\n * Checks if a variable is a function parameter.\n */\nconst isVariableAParameter = (variable: { defs: ReadonlyArray<{ type: string }> }): boolean => {\n return variable.defs.some(def => def.type === \"Parameter\");\n};\n\n/**\n * Traces an identifier back to determine if it originates from a function parameter.\n * Returns detailed information about how the identifier relates to the parameter.\n *\n * This is used to distinguish between:\n * - Props passed through: `({ onClose }) => <button onClick={onClose} />` - destructured-in-signature\n * - Props destructured in body: `(props) => { const { onClose } = props; }` - destructured-in-body\n * - Direct parameter: `(onClose) => ...` - direct-parameter\n * - Internal functions: `const handleClose = () => {}; <button onClick={handleClose} />` - not from parameter\n * - Hook results: `const { mutate } = useMutation(); <button onClick={mutate} />` - not from parameter\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns ParameterOriginResult with isFromParameter and originType if applicable\n * @example\n * // Direct parameter\n * const MyComponent = (onClose) => <button onClick={onClose} />;\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"direct-parameter\" }\n * @example\n * // Destructured in signature\n * const MyComponent = ({ onClose }) => <button onClick={onClose} />;\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"destructured-in-signature\" }\n * @example\n * // Destructured in body\n * const MyComponent = (props) => {\n * const { onClose } = props;\n * return <button onClick={onClose} />;\n * };\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"destructured-in-body\" }\n * @example\n * // Not from parameter (internal function)\n * const MyComponent = () => {\n * const handleClose = () => {};\n * return <button onClick={handleClose} />;\n * };\n * // getIdentifierParameterOrigin(handleClose) => { isFromParameter: false }\n */\nconst getIdentifierParameterOrigin = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): ParameterOriginResult => {\n const scope = context.sourceCode.getScope(identifier);\n const variable = scope.references.find(ref => ref.identifier === identifier)?.resolved;\n\n if (!variable) {\n return { isFromParameter: false };\n }\n\n // Check the variable's definitions\n for (const definition of variable.defs) {\n // Check if defined as a direct function parameter\n if (definition.type === \"Parameter\") {\n // Direct parameter: (onClose) => ...\n return { isFromParameter: true, originType: \"direct-parameter\" };\n }\n\n // Check for destructured variable in body: const { onClose } = props\n // definition.type is \"Variable\" and definition.node is VariableDeclarator\n if (definition.type === \"Variable\") {\n const declarator = definition.node;\n\n // Check if the left side is an ObjectPattern (destructuring)\n if (declarator.id.type === AST_NODE_TYPES.ObjectPattern) {\n const init = declarator.init;\n\n // Check if destructured from an identifier that is a parameter\n if (init?.type === AST_NODE_TYPES.Identifier) {\n const initScope = context.sourceCode.getScope(init);\n const initVariable = initScope.references.find(ref => ref.identifier === init)?.resolved;\n\n if (initVariable && isVariableAParameter(initVariable)) {\n return { isFromParameter: true, originType: \"destructured-in-body\" };\n }\n }\n }\n }\n\n // Check if it's a destructured parameter directly in function signature\n // Pattern: ({ onClose }) => ... or ({ onClose }: Props) => ...\n if (definition.node.type === AST_NODE_TYPES.Property) {\n // Check direct parent - should be ObjectPattern for destructured props\n const objectPattern = definition.node.parent;\n if (objectPattern.type !== AST_NODE_TYPES.ObjectPattern) {\n continue;\n }\n\n // Check if this ObjectPattern is a function parameter\n const objectPatternParent = objectPattern.parent;\n\n if (\n objectPatternParent.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n objectPatternParent.type === AST_NODE_TYPES.FunctionExpression ||\n objectPatternParent.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n // Check if the ObjectPattern is in the params\n const isParam = objectPatternParent.params.includes(objectPattern);\n if (isParam) {\n return { isFromParameter: true, originType: \"destructured-in-signature\" };\n }\n }\n\n // Also check for AssignmentPattern wrapper: ({ onClose = defaultFn }) => ...\n if (objectPatternParent.type === AST_NODE_TYPES.AssignmentPattern) {\n const assignmentParent = objectPatternParent.parent;\n\n if (\n assignmentParent.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n assignmentParent.type === AST_NODE_TYPES.FunctionExpression ||\n assignmentParent.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n const isParam = assignmentParent.params.includes(objectPatternParent);\n if (isParam) {\n return { isFromParameter: true, originType: \"destructured-in-signature\" };\n }\n }\n }\n }\n }\n\n return { isFromParameter: false };\n};\n\n/**\n * Checks if an identifier originates from a function parameter.\n * This is a simplified boolean helper that wraps `getIdentifierParameterOrigin`.\n *\n * Use this when you only need to know if an identifier comes from a parameter,\n * without needing to know how it was destructured.\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns true if the identifier originates from a function parameter\n * @see getIdentifierParameterOrigin for detailed origin information\n */\nexport const isIdentifierFromParameter = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): boolean => getIdentifierParameterOrigin(identifier, context).isFromParameter;\n\n/**\n * Checks if an identifier's parameter comes from a render prop callback.\n *\n * Render prop pattern: `{callback => <Component onClick={callback} />}`\n *\n * The function detects when:\n * 1. The identifier comes from a parameter\n * 2. That parameter's function is inside a JSXExpressionContainer\n * 3. Which is a child of a JSXElement (render prop pattern)\n *\n * This is used to distinguish between:\n * - React component props: `const Modal = ({ onClose }) => ...` - should be flagged\n * - Render prop callbacks: `<MoreMenu>{close => <MenuItem onClick={close} />}</MoreMenu>` - should NOT be flagged\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns true if the identifier comes from a render prop callback parameter\n * @example\n * // Render prop callback - returns true\n * <MoreMenu>\n * {close => <MenuItem onClick={close} />}\n * </MoreMenu>\n * // isIdentifierFromRenderPropCallback(close) => true\n * @example\n * // React component prop - returns false\n * const Modal = ({ onClose }) => <button onClick={onClose} />;\n * // isIdentifierFromRenderPropCallback(onClose) => false\n */\nexport const isIdentifierFromRenderPropCallback = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): boolean => {\n // First check if it even comes from a parameter\n if (!isIdentifierFromParameter(identifier, context)) {\n return false;\n }\n\n // Get the variable that this identifier resolves to\n const scope = context.sourceCode.getScope(identifier);\n const variable = scope.references.find(ref => ref.identifier === identifier)?.resolved;\n\n if (!variable) {\n return false;\n }\n\n // Check each definition of this variable\n for (const definition of variable.defs) {\n if (definition.type !== \"Parameter\") {\n continue;\n }\n\n // Find the function that contains this parameter by walking up from the definition node\n let functionNode:\n | TSESTree.ArrowFunctionExpression\n | TSESTree.FunctionExpression\n | TSESTree.FunctionDeclaration\n | null = null;\n\n let current: TSESTree.Node | undefined = definition.node;\n do {\n if (\n current.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n current.type === AST_NODE_TYPES.FunctionExpression ||\n current.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n functionNode = current;\n break;\n }\n current = current.parent;\n } while (current !== undefined);\n\n if (!functionNode) {\n continue;\n }\n\n // Check if the function is inside a JSXExpressionContainer (render prop pattern)\n // Pattern: <Component>{callback => ...}</Component>\n const parent = functionNode.parent;\n if (parent.type === AST_NODE_TYPES.JSXExpressionContainer) {\n // Verify the JSXExpressionContainer is a child of a JSXElement\n const jsxContainerParent = parent.parent;\n if (\n jsxContainerParent.type === AST_NODE_TYPES.JSXElement ||\n jsxContainerParent.type === AST_NODE_TYPES.JSXFragment\n ) {\n return true;\n }\n }\n }\n\n return false;\n};\n"]}