@trackunit/eslint-plugin-trackunit 0.4.7 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/src/lib/config/index.d.ts +21 -21
- package/src/lib/config/plugins.d.ts +7 -7
- package/src/lib/config/presets/base.d.ts +14 -14
- package/src/lib/config/presets/react.d.ts +7 -7
- package/src/lib/rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public.d.ts +3 -4
- package/src/lib/rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public.js +60 -57
- package/src/lib/rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks.d.ts +4 -2
- package/src/lib/rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks.js +6 -2
- package/src/lib/rules/no-typescript-assertion/no-typescript-assertion.d.ts +5 -4
- package/src/lib/rules/no-typescript-assertion/no-typescript-assertion.js +57 -72
- package/src/lib/rules/require-list-item-virtualization-props/require-list-item-virtualization-props.js +1 -1
- package/src/lib/rules-map.d.ts +7 -8
- package/src/index.js.map +0 -1
- package/src/lib/config/fragments/ignores.js.map +0 -1
- package/src/lib/config/fragments/import-rules.js.map +0 -1
- package/src/lib/config/fragments/jest-overrides.js.map +0 -1
- package/src/lib/config/fragments/jsdoc-rules.js.map +0 -1
- package/src/lib/config/fragments/module-boundaries.js.map +0 -1
- package/src/lib/config/fragments/react-rules.js.map +0 -1
- package/src/lib/config/fragments/restricted-imports.js.map +0 -1
- package/src/lib/config/fragments/testing-library.js.map +0 -1
- package/src/lib/config/fragments/typescript-rules.js.map +0 -1
- package/src/lib/config/index.js.map +0 -1
- package/src/lib/config/plugins.js.map +0 -1
- package/src/lib/config/presets/base.js.map +0 -1
- package/src/lib/config/presets/e2e.js.map +0 -1
- package/src/lib/config/presets/react.js.map +0 -1
- package/src/lib/config/presets/server.js.map +0 -1
- package/src/lib/config/utils.js.map +0 -1
- package/src/lib/config-helpers/create-skip-when.js.map +0 -1
- package/src/lib/rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array.js.map +0 -1
- package/src/lib/rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match.js.map +0 -1
- package/src/lib/rules/no-internal-barrel-files/examples.d.ts +0 -80
- package/src/lib/rules/no-internal-barrel-files/examples.js +0 -84
- package/src/lib/rules/no-internal-barrel-files/examples.js.map +0 -1
- package/src/lib/rules/no-internal-barrel-files/no-internal-barrel-files.js.map +0 -1
- package/src/lib/rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public.js.map +0 -1
- package/src/lib/rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks.js.map +0 -1
- package/src/lib/rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop.js.map +0 -1
- package/src/lib/rules/no-typescript-assertion/examples.d.ts +0 -1
- package/src/lib/rules/no-typescript-assertion/examples.js +0 -45
- package/src/lib/rules/no-typescript-assertion/examples.js.map +0 -1
- package/src/lib/rules/no-typescript-assertion/no-typescript-assertion.js.map +0 -1
- package/src/lib/rules/prefer-destructured-imports/prefer-destructured-imports.js.map +0 -1
- package/src/lib/rules/prefer-event-specific-callback-naming/name-suggestion-strategies.js.map +0 -1
- package/src/lib/rules/prefer-event-specific-callback-naming/prefer-event-specific-callback-naming.js.map +0 -1
- package/src/lib/rules/prefer-event-specific-callback-naming/strategies/string-based.js.map +0 -1
- package/src/lib/rules/prefer-event-specific-callback-naming/strategies/type-based.js.map +0 -1
- package/src/lib/rules/prefer-event-specific-callback-naming/utils.js.map +0 -1
- package/src/lib/rules/prefer-field-components/prefer-field-components.js.map +0 -1
- package/src/lib/rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props.js.map +0 -1
- package/src/lib/rules/require-classname-alternatives/require-classname-alternatives.js.map +0 -1
- package/src/lib/rules/require-list-item-virtualization-props/require-list-item-virtualization-props.js.map +0 -1
- package/src/lib/rules/require-optional-prop-initialization/require-optional-prop-initialization.js.map +0 -1
- package/src/lib/rules/require-optional-prop-initialization/suggestion-utils.js.map +0 -1
- package/src/lib/rules-map.js.map +0 -1
- package/src/lib/utils/ast-utils.js.map +0 -1
- package/src/lib/utils/classname-utils.js.map +0 -1
- package/src/lib/utils/file-utils.js.map +0 -1
- package/src/lib/utils/import-utils.js.map +0 -1
- package/src/lib/utils/nx-utils.js.map +0 -1
- package/src/lib/utils/package-utils.js.map +0 -1
- package/src/lib/utils/typescript-utils.js.map +0 -1
|
@@ -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 * - `getParameterRestUsage()` - Get info about parameter accessed via rest params\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 * - `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\n/**\n * Check if a parameter is accessed via rest parameters (e.g., rest.paramName)\n * and return information about the rest parameter usage\n */\nconst getParameterRestUsage = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): { isUsedViaRest: boolean; restParamName?: string; restParam?: TSESTree.Parameter } | null => {\n // Look for rest elements in both direct params and inside object patterns\n const restParameters: Array<{ name: string; param: TSESTree.Parameter }> = [];\n\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 { isUsedViaRest: 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 {\n isUsedViaRest: true,\n restParamName: restParam.name,\n restParam: restParam.param,\n };\n }\n }\n\n return { isUsedViaRest: false };\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 // Check if the function returns JSX\n const hasJSXReturn = (body: TSESTree.Node): boolean => {\n if (body.type === AST_NODE_TYPES.JSXElement || body.type === AST_NODE_TYPES.JSXFragment) {\n return true;\n }\n // Handle conditional expressions that contain JSX: condition ? <JSX /> : null\n if (body.type === AST_NODE_TYPES.ConditionalExpression) {\n return hasJSXReturn(body.consequent) || hasJSXReturn(body.alternate);\n }\n if (body.type === AST_NODE_TYPES.BlockStatement) {\n return body.body.some(stmt => {\n if (stmt.type === AST_NODE_TYPES.ReturnStatement && stmt.argument) {\n return hasJSXReturn(stmt.argument);\n }\n return false;\n });\n }\n return false;\n };\n\n return hasJSXReturn(node.body);\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"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"classname-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/classname-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { AST_NODE_TYPES, TSESTree } from \"@typescript-eslint/utils\";\n\n/**\n * Utility functions for finding and analyzing Tailwind CSS classnames in ESLint rules.\n *\n * This module provides a centralized way to detect classname usage patterns across:\n * - JSX `className` and `class` attributes\n * - Variables named with `...Class` or `...ClassName` suffixes\n * - Tailwind utility functions: `cvaMerge`, `twMerge`, `cva`, `tw`, `twx`, `tws`, `cn`, `clsx`, `classNames`, `twJoin`\n *\n * ## Core Concepts\n *\n * ### ClassnameLocation\n * Represents a single location where a classname string value is found.\n * Contains the string value, the AST node for reporting/fixing, and metadata.\n *\n * ### ClassnameContext\n * Describes where a classname was found (JSX attribute, function call, variable, etc.)\n *\n * ## Usage in ESLint Rules\n *\n * ```typescript\n * import { findClassnameStrings, TAILWIND_FUNCTIONS, isClassnameVariable } from \"./classname-utils\";\n *\n * // In a CallExpression handler:\n * CallExpression(node) {\n * const locations = findClassnameStrings(node);\n * for (const location of locations) {\n * // Check location.value for banned patterns\n * // Report on location.reportNode\n * // Fix using location.fixNode\n * }\n * }\n * ```\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Context describing where a classname was found\n */\nexport type ClassnameContext =\n | { type: \"jsx-attribute\"; attributeName: string }\n | { type: \"function-call\"; functionName: string; argumentIndex: number }\n | { type: \"cva-variant\"; functionName: string; variantPath: Array<string> }\n | { type: \"variable\"; variableName: string }\n | { type: \"array-element\"; parentContext: ClassnameContext; elementIndex: number };\n\n/**\n * Represents a location where a classname string value is found\n */\nexport type ClassnameLocation = {\n /** The extracted string value (for template literals, only static parts) */\n value: string;\n /** The AST node to use when reporting errors */\n reportNode: TSESTree.Node;\n /** The AST node to use when creating fixes (string literal or template literal) */\n fixNode: TSESTree.Literal | TSESTree.TemplateLiteral;\n /** Context describing where this classname was found */\n context: ClassnameContext;\n};\n\n/**\n * Result of extracting a string value from a node\n */\ntype StringExtractionResult = {\n value: string;\n node: TSESTree.Literal | TSESTree.TemplateLiteral;\n} | null;\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n/**\n * Function names that accept Tailwind class strings as arguments.\n * These are commonly used for class merging and conditional class application.\n *\n * Corresponds to the `tailwindFunctions` config in .prettierrc for Prettier's\n * Tailwind CSS plugin.\n */\nexport const TAILWIND_FUNCTIONS = [\n \"cva\",\n \"cvaMerge\",\n \"tw\",\n \"twx\",\n \"tws\",\n \"twMerge\",\n \"twJoin\",\n \"cn\",\n \"clsx\",\n \"classNames\",\n] as const;\n\nexport type TailwindFunction = (typeof TAILWIND_FUNCTIONS)[number];\n\n/**\n * Variable name patterns that indicate a classname value.\n * Matches variables like: containerClass, buttonClassName, rootClasses\n */\nconst CLASSNAME_VARIABLE_PATTERNS = [/Class$/, /ClassName$/, /Classes$/] as const;\n\n/**\n * JSX attribute names that contain classname values\n */\nexport const CLASSNAME_ATTRIBUTES = [\"className\", \"class\"] as const;\n\n// =============================================================================\n// Detection Helpers\n// =============================================================================\n\n/**\n * Check if a function name is a known Tailwind utility function\n */\nexport const isTailwindFunction = (name: string): name is TailwindFunction => {\n return TAILWIND_FUNCTIONS.some(fn => fn === name);\n};\n\n/**\n * Check if a variable name indicates it contains classnames\n */\nexport const isClassnameVariable = (name: string): boolean => {\n return CLASSNAME_VARIABLE_PATTERNS.some(pattern => pattern.test(name));\n};\n\n/**\n * Check if a JSX attribute name is a classname attribute\n */\nexport const isClassnameAttribute = (name: string): boolean => {\n return CLASSNAME_ATTRIBUTES.some(attr => attr === name);\n};\n\n/**\n * Get the function name from a CallExpression callee\n */\nexport const getCalleeName = (callee: TSESTree.CallExpression[\"callee\"]): string | null => {\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name;\n }\n if (callee.type === AST_NODE_TYPES.MemberExpression && callee.property.type === AST_NODE_TYPES.Identifier) {\n return callee.property.name;\n }\n return null;\n};\n\n// =============================================================================\n// String Extraction\n// =============================================================================\n\n/**\n * Extract a string value from a Literal node\n */\nconst extractFromLiteral = (node: TSESTree.Literal): StringExtractionResult => {\n if (typeof node.value === \"string\") {\n return { value: node.value, node };\n }\n return null;\n};\n\n/**\n * Extract the static parts of a TemplateLiteral as a single string.\n * Template expressions are replaced with a single space to preserve word boundaries.\n */\nconst extractFromTemplateLiteral = (node: TSESTree.TemplateLiteral): StringExtractionResult => {\n // Join static parts with spaces (representing where expressions would be)\n const value = node.quasis.map(quasi => quasi.value.raw).join(\" \");\n return { value, node };\n};\n\n/**\n * Extract string value from a node that might contain a classname string.\n * Handles Literal and TemplateLiteral nodes.\n */\nconst extractStringValue = (node: TSESTree.Node): StringExtractionResult => {\n switch (node.type) {\n case AST_NODE_TYPES.Literal:\n return extractFromLiteral(node);\n case AST_NODE_TYPES.TemplateLiteral:\n return extractFromTemplateLiteral(node);\n default:\n return null;\n }\n};\n\n// =============================================================================\n// Array Traversal\n// =============================================================================\n\n/**\n * Extract classname locations from an ArrayExpression.\n * Handles arrays like: [\"flex\", \"items-center\", \"bg-primary-500\"]\n */\nconst extractFromArray = (\n node: TSESTree.ArrayExpression,\n parentContext: ClassnameContext\n): Array<ClassnameLocation> => {\n const locations: Array<ClassnameLocation> = [];\n\n node.elements.forEach((element, index) => {\n if (!element || element.type === AST_NODE_TYPES.SpreadElement) {\n return;\n }\n\n const extracted = extractStringValue(element);\n if (extracted) {\n locations.push({\n value: extracted.value,\n reportNode: element,\n fixNode: extracted.node,\n context: { type: \"array-element\", parentContext, elementIndex: index },\n });\n }\n });\n\n return locations;\n};\n\n// =============================================================================\n// CVA/CVAMerge Object Traversal\n// =============================================================================\n\n/**\n * Recursively extract classname locations from a CVA options object.\n *\n * CVA structure:\n * ```\n * cva(baseClasses, {\n * variants: {\n * variantName: {\n * variantValue: \"classnames here\",\n * }\n * },\n * compoundVariants: [\n * { variantName: \"value\", className: \"classnames\" }\n * ],\n * defaultVariants: { ... }\n * })\n * ```\n */\nconst extractFromCvaObject = (\n node: TSESTree.ObjectExpression,\n functionName: string,\n currentPath: Array<string> = []\n): Array<ClassnameLocation> => {\n const locations: Array<ClassnameLocation> = [];\n\n for (const property of node.properties) {\n if (property.type !== AST_NODE_TYPES.Property) {\n continue;\n }\n\n const keyName = getPropertyKeyName(property.key);\n if (!keyName) {\n continue;\n }\n\n const propertyPath = [...currentPath, keyName];\n\n // Skip defaultVariants as it doesn't contain classnames\n if (keyName === \"defaultVariants\") {\n continue;\n }\n\n // Recurse into nested objects (variants, compoundVariants entries, etc.)\n if (property.value.type === AST_NODE_TYPES.ObjectExpression) {\n locations.push(...extractFromCvaObject(property.value, functionName, propertyPath));\n continue;\n }\n\n // Handle arrays (compoundVariants array, or array of class strings)\n if (property.value.type === AST_NODE_TYPES.ArrayExpression) {\n // Check if this is an array of objects (like compoundVariants)\n const hasObjectElements = property.value.elements.some(el => el?.type === AST_NODE_TYPES.ObjectExpression);\n\n if (hasObjectElements) {\n // Recurse into each object in the array\n property.value.elements.forEach((element, index) => {\n if (element?.type === AST_NODE_TYPES.ObjectExpression) {\n locations.push(...extractFromCvaObject(element, functionName, [...propertyPath, `[${index}]`]));\n }\n });\n } else {\n // This is an array of class strings\n const arrayContext: ClassnameContext = {\n type: \"cva-variant\",\n functionName,\n variantPath: propertyPath,\n };\n locations.push(...extractFromArray(property.value, arrayContext));\n }\n continue;\n }\n\n // Extract string values at leaf nodes\n const extracted = extractStringValue(property.value);\n if (extracted) {\n locations.push({\n value: extracted.value,\n reportNode: property.value,\n fixNode: extracted.node,\n context: {\n type: \"cva-variant\",\n functionName,\n variantPath: propertyPath,\n },\n });\n }\n }\n\n return locations;\n};\n\n/**\n * Get the name of an object property key\n */\nconst getPropertyKeyName = (key: TSESTree.Property[\"key\"]): string | null => {\n if (key.type === AST_NODE_TYPES.Identifier) {\n return key.name;\n }\n if (key.type === AST_NODE_TYPES.Literal && typeof key.value === \"string\") {\n return key.value;\n }\n return null;\n};\n\n// =============================================================================\n// Function Call Extraction\n// =============================================================================\n\n/**\n * Extract classname locations from a Tailwind function call.\n *\n * Handles various argument patterns:\n * - String literals: twMerge(\"flex items-center\")\n * - Template literals: twMerge(`flex ${condition && \"hidden\"}`)\n * - Arrays: cvaMerge([\"flex\", \"items-center\"], options)\n * - CVA options objects: cva(base, { variants: { ... } })\n */\nconst extractFromFunctionCall = (node: TSESTree.CallExpression): Array<ClassnameLocation> => {\n const calleeName = getCalleeName(node.callee);\n if (!calleeName || !isTailwindFunction(calleeName)) {\n return [];\n }\n\n const locations: Array<ClassnameLocation> = [];\n const isCvaStyle = calleeName === \"cva\" || calleeName === \"cvaMerge\";\n\n node.arguments.forEach((arg, argIndex) => {\n const baseContext: ClassnameContext = {\n type: \"function-call\",\n functionName: calleeName,\n argumentIndex: argIndex,\n };\n\n // Handle string literals\n const extracted = extractStringValue(arg);\n if (extracted) {\n locations.push({\n value: extracted.value,\n reportNode: arg,\n fixNode: extracted.node,\n context: baseContext,\n });\n return;\n }\n\n // Handle array arguments\n if (arg.type === AST_NODE_TYPES.ArrayExpression) {\n locations.push(...extractFromArray(arg, baseContext));\n return;\n }\n\n // Handle CVA options object (typically second argument)\n if (isCvaStyle && arg.type === AST_NODE_TYPES.ObjectExpression) {\n locations.push(...extractFromCvaObject(arg, calleeName));\n }\n });\n\n return locations;\n};\n\n// =============================================================================\n// JSX Attribute Extraction\n// =============================================================================\n\n/**\n * Extract classname locations from a JSX attribute (className or class).\n *\n * Handles various value patterns:\n * - String literals: className=\"flex items-center\"\n * - Expression with string: className={\"flex items-center\"}\n * - Template literals: className={`flex ${condition && \"hidden\"}`}\n */\nconst extractFromJsxAttribute = (node: TSESTree.JSXAttribute): Array<ClassnameLocation> => {\n if (node.name.type !== AST_NODE_TYPES.JSXIdentifier) {\n return [];\n }\n\n const attrName = node.name.name;\n if (!isClassnameAttribute(attrName)) {\n return [];\n }\n\n const attrValue = node.value;\n if (!attrValue) {\n return [];\n }\n\n const context: ClassnameContext = {\n type: \"jsx-attribute\",\n attributeName: attrName,\n };\n\n // Direct string literal: className=\"flex items-center\"\n if (attrValue.type === AST_NODE_TYPES.Literal) {\n const extracted = extractFromLiteral(attrValue);\n if (extracted) {\n return [\n {\n value: extracted.value,\n reportNode: node,\n fixNode: extracted.node,\n context,\n },\n ];\n }\n }\n\n // JSX Expression: className={...}\n if (attrValue.type === AST_NODE_TYPES.JSXExpressionContainer) {\n const expression = attrValue.expression;\n\n // Skip empty expressions\n if (expression.type === AST_NODE_TYPES.JSXEmptyExpression) {\n return [];\n }\n\n // String literal in expression: className={\"flex items-center\"}\n const extracted = extractStringValue(expression);\n if (extracted) {\n return [\n {\n value: extracted.value,\n reportNode: node,\n fixNode: extracted.node,\n context,\n },\n ];\n }\n\n // Note: We don't recurse into function calls here as they're handled\n // separately by the CallExpression handler in the rule\n }\n\n return [];\n};\n\n// =============================================================================\n// Variable Declaration Extraction\n// =============================================================================\n\n/**\n * Extract classname locations from a variable declaration with a classname-like name.\n *\n * Example: const buttonClass = \"flex items-center\";\n */\nconst extractFromVariableDeclarator = (node: TSESTree.VariableDeclarator): Array<ClassnameLocation> => {\n if (node.id.type !== AST_NODE_TYPES.Identifier) {\n return [];\n }\n\n const varName = node.id.name;\n if (!isClassnameVariable(varName)) {\n return [];\n }\n\n if (!node.init) {\n return [];\n }\n\n const context: ClassnameContext = {\n type: \"variable\",\n variableName: varName,\n };\n\n // Handle string literal\n const extracted = extractStringValue(node.init);\n if (extracted) {\n return [\n {\n value: extracted.value,\n reportNode: node.init,\n fixNode: extracted.node,\n context,\n },\n ];\n }\n\n // Handle array of strings\n if (node.init.type === AST_NODE_TYPES.ArrayExpression) {\n return extractFromArray(node.init, context);\n }\n\n // Note: Function calls in variable initializers are handled separately\n // by the CallExpression handler\n\n return [];\n};\n\n// =============================================================================\n// Unified Entry Points\n// =============================================================================\n\n/**\n * Find all classname string locations in a CallExpression node.\n *\n * Use this in your ESLint rule's CallExpression handler to process\n * Tailwind utility function calls like twMerge, cvaMerge, etc.\n *\n * @example\n * ```typescript\n * CallExpression(node) {\n * const locations = findClassnameStringsInCall(node);\n * for (const location of locations) {\n * if (hasBannedPattern(location.value)) {\n * context.report({ node: location.reportNode, ... });\n * }\n * }\n * }\n * ```\n */\nexport const findClassnameStringsInCall = (node: TSESTree.CallExpression): Array<ClassnameLocation> => {\n return extractFromFunctionCall(node);\n};\n\n/**\n * Find all classname string locations in a JSXAttribute node.\n *\n * Use this in your ESLint rule's JSXAttribute handler to process\n * className and class attributes.\n *\n * @example\n * ```typescript\n * JSXAttribute(node) {\n * const locations = findClassnameStringsInAttribute(node);\n * for (const location of locations) {\n * if (hasBannedPattern(location.value)) {\n * context.report({ node: location.reportNode, ... });\n * }\n * }\n * }\n * ```\n */\nexport const findClassnameStringsInAttribute = (node: TSESTree.JSXAttribute): Array<ClassnameLocation> => {\n return extractFromJsxAttribute(node);\n};\n\n/**\n * Find all classname string locations in a VariableDeclarator node.\n *\n * Use this in your ESLint rule's VariableDeclarator handler to process\n * variables with classname-like names.\n *\n * @example\n * ```typescript\n * VariableDeclarator(node) {\n * const locations = findClassnameStringsInVariable(node);\n * for (const location of locations) {\n * if (hasBannedPattern(location.value)) {\n * context.report({ node: location.reportNode, ... });\n * }\n * }\n * }\n * ```\n */\nconst findClassnameStringsInVariable = (node: TSESTree.VariableDeclarator): Array<ClassnameLocation> => {\n return extractFromVariableDeclarator(node);\n};\n\n// =============================================================================\n// Utility Helpers for Fixing\n// =============================================================================\n\n/**\n * Split a classname string into individual class names.\n * Handles whitespace-separated classes.\n */\nexport const splitClasses = (value: string): Array<string> => {\n return value.split(/\\s+/).filter(Boolean);\n};\n\n/**\n * Join class names into a single string.\n */\nexport const joinClasses = (classes: Array<string>): string => {\n return classes.join(\" \");\n};\n\n/**\n * Create a JSON-formatted array string from an array of class names.\n * Useful for auto-fix operations.\n */\nexport const formatAsArray = (classes: Array<string>): string => {\n return JSON.stringify(classes);\n};\n\n/**\n * Get the quote character used in a string literal.\n */\nconst getQuoteChar = (node: TSESTree.Literal): string => {\n if (typeof node.value === \"string\" && node.raw) {\n return node.raw.charAt(0);\n }\n return '\"';\n};\n\n/**\n * Create a quoted string with the same quote style as the original.\n */\nconst quoteString = (value: string, originalNode: TSESTree.Literal): string => {\n const quote = getQuoteChar(originalNode);\n return `${quote}${value}${quote}`;\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/file-utils.ts"],"names":[],"mappings":";;;;AAAA,+CAAyB;AACzB,mDAA6B;AAE7B;;;;;GAKG;AAIH;;;;;;;;;;;;GAYG;AACI,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAE,QAAgB,EAAiB,EAAE;IACnF,IAAI,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;IAEzC,OAAO,UAAU,KAAK,IAAI,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAEnD,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAfW,QAAA,eAAe,mBAe1B","sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\n\n/**\n * Utility functions for working with files in ESLint rules.\n *\n * ## Main Functions\n * - `findNearestFile()` - Find the nearest file by walking up the directory tree\n */\n\n\n\n/**\n * Find the nearest file with a given name by walking up the directory tree.\n *\n * @param filePath - The starting file path\n * @param fileName - The file name to search for (e.g., \"package.json\", \"project.json\")\n * @returns Absolute path to the file or null if not found\n * @example\n * const pkgPath = findNearestFile(\"/workspace/libs/my-lib/src/index.ts\", \"package.json\");\n * // Returns: \"/workspace/libs/my-lib/package.json\"\n * @example\n * const projectPath = findNearestFile(\"/workspace/libs/my-lib/src/index.ts\", \"project.json\");\n * // Returns: \"/workspace/libs/my-lib/project.json\"\n */\nexport const findNearestFile = (filePath: string, fileName: string): string | null => {\n let currentDir = path.dirname(filePath);\n const root = path.parse(currentDir).root;\n\n while (currentDir !== root) {\n const targetPath = path.join(currentDir, fileName);\n\n if (fs.existsSync(targetPath)) {\n return targetPath;\n }\n\n currentDir = path.dirname(currentDir);\n }\n\n return null;\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"import-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/import-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { AST_NODE_TYPES, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\n\n/**\n * Utility functions for manipulating import statements in TypeScript ESLint rules.\n *\n * ## Design Philosophy\n * Rules should focus on WHAT to do, not HOW to do it. This utility handles all the\n * implementation details: semicolons, newlines, alphabetical sorting, merging, etc.\n *\n * ## Main Functions\n * - `addImportSpecifiers()` - Add new imports or merge with existing ones\n * - `replaceNamespaceWithDestructured()` - Replace namespace imports (e.g., `import React from \"react\"`)\n * - `addSingleImportSpecifier()` - Convenience for adding a single import\n *\n * ## Helper Functions\n * - `findImportDeclaration()` - Find existing import for a package\n * - `hasImportSpecifier()` - Check if specific import already exists\n * - `getImportSpecifiers()` - Extract specifiers from an import\n */\n\n/**\n * Internal helper to check if an import statement ends with a semicolon\n */\nconst hasSemicolon = (sourceCode: Readonly<TSESLint.SourceCode>, node: TSESTree.ImportDeclaration): boolean => {\n const nodeText = sourceCode.getText(node);\n return nodeText.trimEnd().endsWith(\";\");\n};\n\n/**\n * Find an existing import declaration for a given package.\n *\n * @example\n * // Returns the import node if it exists:\n * // import { useState } from \"react\";\n * const reactImport = findImportDeclaration(sourceCode, \"react\");\n */\nexport const findImportDeclaration = (\n sourceCode: Readonly<TSESLint.SourceCode>,\n packageName: string\n): TSESTree.ImportDeclaration | undefined => {\n const found = sourceCode.ast.body.find(\n (node): node is TSESTree.ImportDeclaration =>\n node.type === AST_NODE_TYPES.ImportDeclaration && node.source.value === packageName\n );\n return found;\n};\n\n/**\n * Check if a specific specifier is already imported from a package.\n *\n * @example\n * // File has: import { useState, useEffect } from \"react\";\n * hasImportSpecifier(sourceCode, \"react\", \"useState\") // → true\n * hasImportSpecifier(sourceCode, \"react\", \"useRef\") // → false\n */\nconst hasImportSpecifier = (\n sourceCode: Readonly<TSESLint.SourceCode>,\n packageName: string,\n specifierName: string\n): boolean => {\n return sourceCode.ast.body.some(\n node =>\n node.type === AST_NODE_TYPES.ImportDeclaration &&\n node.source.value === packageName &&\n node.specifiers.some(\n specifier =>\n specifier.type === AST_NODE_TYPES.ImportSpecifier &&\n specifier.imported.type === AST_NODE_TYPES.Identifier &&\n specifier.imported.name === specifierName\n )\n );\n};\n\n/**\n * Get existing import specifiers from an import declaration.\n *\n * @example\n * // Given: import { useState, useEffect } from \"react\";\n * getImportSpecifiers(importNode) // → Set([\"useState\", \"useEffect\"])\n */\nexport const getImportSpecifiers = (importNode: TSESTree.ImportDeclaration): Set<string> => {\n return new Set(\n importNode.specifiers\n .filter((s): s is TSESTree.ImportSpecifier => s.type === AST_NODE_TYPES.ImportSpecifier)\n .map(s => (s.imported.type === AST_NODE_TYPES.Identifier ? s.imported.name : \"\"))\n .filter(Boolean)\n );\n};\n\ninterface AddImportSpecifiersOptions {\n sourceCode: Readonly<TSESLint.SourceCode>;\n fixer: TSESLint.RuleFixer;\n packageName: string;\n /** Specifiers to add (e.g., [\"useState\", \"useEffect\"]) */\n specifiers: Array<string>;\n /** Optional: Existing import to merge into. If not provided, creates a new import statement */\n existingImport?: TSESTree.ImportDeclaration;\n}\n\n/**\n * Internal helper to build a properly formatted import statement with sorted specifiers\n */\nconst buildImportStatement = (\n sourceCode: Readonly<TSESLint.SourceCode>,\n packageName: string,\n specifiers: Iterable<string>,\n referenceNode?: TSESTree.ImportDeclaration\n): string => {\n const sortedSpecifiers = Array.from(specifiers).sort().join(\", \");\n const semicolon = referenceNode && hasSemicolon(sourceCode, referenceNode) ? \";\" : \";\";\n return `import { ${sortedSpecifiers} } from \"${packageName}\"${semicolon}`;\n};\n\n/**\n * Add import specifiers to an existing import or create a new import statement.\n * Automatically handles merging, semicolons, newlines, alphabetical sorting, and formatting.\n *\n * @example\n * // Case 1: No existing import - creates new\n * // Before: (no imports)\n * // After: import { useEffect, useState } from \"react\";\n * @example\n * // Case 2: Merge with existing import\n * // Before: import { useState } from \"react\";\n * // After: import { useEffect, useState } from \"react\";\n */\nexport const addImportSpecifiers = (options: AddImportSpecifiersOptions): Array<TSESLint.RuleFix> => {\n const { sourceCode, fixer, packageName, specifiers, existingImport } = options;\n const fixes: Array<TSESLint.RuleFix> = [];\n\n if (existingImport) {\n // Merge with existing import\n const existingSpecifiers = getImportSpecifiers(existingImport);\n const combinedSpecifiers = new Set([...existingSpecifiers, ...specifiers]);\n const importStatement = buildImportStatement(sourceCode, packageName, combinedSpecifiers, existingImport);\n\n fixes.push(fixer.replaceText(existingImport, importStatement));\n } else {\n // Create new import statement\n const lastImport = sourceCode.ast.body.find(\n (node): node is TSESTree.ImportDeclaration => node.type === AST_NODE_TYPES.ImportDeclaration\n );\n\n if (lastImport) {\n // Add after existing imports with leading newline\n const importStatement = \"\\n\" + buildImportStatement(sourceCode, packageName, specifiers, lastImport);\n fixes.push(fixer.insertTextAfter(lastImport, importStatement));\n } else {\n // No imports exist - add at the beginning with trailing newlines\n const firstNode = sourceCode.ast.body[0];\n if (firstNode) {\n const importStatement = buildImportStatement(sourceCode, packageName, specifiers) + \"\\n\\n\";\n fixes.push(fixer.insertTextBefore(firstNode, importStatement));\n }\n }\n }\n\n return fixes;\n};\n\ninterface AddSingleImportSpecifierOptions {\n sourceCode: Readonly<TSESLint.SourceCode>;\n fixer: TSESLint.RuleFixer;\n packageName: string;\n /** The specifier to add (e.g., \"useState\") */\n specifier: string;\n}\n\n/**\n * Add a single import specifier - convenience wrapper around addImportSpecifiers.\n * Automatically finds and merges with existing imports from the same package.\n *\n * @example\n * // Before: import { useState } from \"react\";\n * // After: import { useEffect, useState } from \"react\";\n * addSingleImportSpecifier({ sourceCode, fixer, packageName: \"react\", specifier: \"useEffect\" })\n */\nconst addSingleImportSpecifier = (options: AddSingleImportSpecifierOptions): Array<TSESLint.RuleFix> => {\n const { sourceCode, packageName, specifier } = options;\n const existingImport = findImportDeclaration(sourceCode, packageName);\n\n return addImportSpecifiers({\n ...options,\n specifiers: [specifier],\n existingImport,\n });\n};\n\ninterface ReplaceNamespaceWithDestructuredOptions {\n sourceCode: Readonly<TSESLint.SourceCode>;\n fixer: TSESLint.RuleFixer;\n packageName: string;\n /** The namespace/default import statement to be replaced (e.g., `import React from \"react\"`) */\n namespaceImportToReplace: TSESTree.ImportDeclaration;\n /** Specifiers to add to the destructured import (e.g., [\"useState\", \"useEffect\"]) */\n specifiersToAdd: Iterable<string>;\n /** Optional: A separate destructured import to merge everything into (e.g., `import { FC } from \"react\"`) */\n mergeIntoImport?: TSESTree.ImportDeclaration;\n}\n\n/**\n * Replace a namespace/default import with destructured imports.\n * Automatically handles merging, semicolons, sorting, and formatting.\n *\n * ## Example 1: Replace in-place (no other import)\n * ```typescript\n * // Before:\n * import React from \"react\";\n * React.useEffect(() => {}, []);\n *\n * // After:\n * import { useEffect } from \"react\";\n * useEffect(() => {}, []);\n * ```\n *\n * ## Example 2: Merge with existing destructured import\n * ```typescript\n * // Before:\n * import React from \"react\"; // ← namespaceImportToReplace\n * import { useState } from \"react\"; // ← mergeIntoImport\n * React.useEffect(() => {}, []);\n *\n * // After:\n * import { useEffect, useState } from \"react\"; // ← Merged!\n * useEffect(() => {}, []);\n * ```\n *\n * @param namespaceImportToReplace - The namespace import to remove/replace\n * @param specifiersToAdd - New specifiers to add\n * @param mergeIntoImport - Optional separate destructured import to merge everything into\n */\nexport const replaceNamespaceWithDestructured = (\n options: ReplaceNamespaceWithDestructuredOptions\n): Array<TSESLint.RuleFix> => {\n const { sourceCode, fixer, packageName, namespaceImportToReplace, specifiersToAdd, mergeIntoImport } = options;\n const fixes: Array<TSESLint.RuleFix> = [];\n\n // Get any existing destructured specifiers from the namespace import itself\n const existingSpecifiersInNamespace = getImportSpecifiers(namespaceImportToReplace);\n const allNewSpecifiers = new Set([...existingSpecifiersInNamespace, ...specifiersToAdd]);\n\n if (mergeIntoImport && mergeIntoImport !== namespaceImportToReplace) {\n // Scenario: We have TWO imports - merge everything into the destructured one and remove the namespace one\n const existingSpecifiers = getImportSpecifiers(mergeIntoImport);\n const combinedSpecifiers = new Set([...existingSpecifiers, ...allNewSpecifiers]);\n const importStatement = buildImportStatement(sourceCode, packageName, combinedSpecifiers, mergeIntoImport);\n\n fixes.push(fixer.replaceText(mergeIntoImport, importStatement));\n fixes.push(fixer.remove(namespaceImportToReplace));\n } else {\n // Scenario: Only ONE import - replace the namespace import in-place\n const importStatement = buildImportStatement(sourceCode, packageName, allNewSpecifiers, namespaceImportToReplace);\n fixes.push(fixer.replaceText(namespaceImportToReplace, importStatement));\n }\n\n return fixes;\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nx-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/nx-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from \"fs\";\nimport { findNearestFile } from \"./file-utils\";\n\n/**\n * Utility functions for working with NX project metadata in ESLint rules.\n *\n * ## Main Functions\n * - `getProjectMetadata()` - Get NX project metadata from project.json\n * - `projectMatchesCriteria()` - Check if project matches given criteria\n */\n\nexport type ProjectMetadata = {\n name: string;\n tags: Array<string>;\n targets: Array<string>;\n projectJsonPath: string;\n};\n\nexport type MatchCriteria = {\n tags?: Array<string>;\n targets?: Array<string>;\n tagsMatchMode?: \"some\" | \"every\";\n targetsMatchMode?: \"some\" | \"every\";\n};\n\n/**\n * Cache for project metadata to avoid reading files multiple times.\n * Key is the absolute path to project.json, value is the parsed metadata.\n */\nconst metadataCache = new Map<string, ProjectMetadata>();\n\n/**\n * Get NX project metadata from the nearest project.json file.\n *\n * @param filePath - Absolute path to a file in the project\n * @returns Project metadata or null if no project.json found\n * @example\n * const metadata = getProjectMetadata(\"/workspace/libs/my-lib/src/index.ts\");\n * // Returns: { name: \"my-lib\", tags: [\"type:react\"], targets: [\"build\", \"test\"], ... }\n */\nexport const getProjectMetadata = (filePath: string): ProjectMetadata | null => {\n const projectJsonPath = findNearestFile(filePath, \"project.json\");\n\n if (!projectJsonPath) {\n return null;\n }\n\n // Check cache first\n if (metadataCache.has(projectJsonPath)) {\n return metadataCache.get(projectJsonPath) ?? null;\n }\n\n try {\n const content = fs.readFileSync(projectJsonPath, \"utf8\");\n const projectJson = JSON.parse(content);\n\n const metadata: ProjectMetadata = {\n name: projectJson.name ?? \"\",\n tags: projectJson.tags ?? [],\n targets:\n typeof projectJson.targets === \"object\" && projectJson.targets !== null ? Object.keys(projectJson.targets) : [],\n projectJsonPath,\n };\n\n // Cache the result\n metadataCache.set(projectJsonPath, metadata);\n\n return metadata;\n } catch {\n return null;\n }\n};\n\n/**\n * Check if project metadata matches the given criteria.\n *\n * @param metadata - Project metadata to check\n * @param criteria - Criteria to match against\n * @returns True if metadata matches all criteria\n * @example\n * // Check if project has the \"scope:tool\" tag\n * projectMatchesCriteria(metadata, { tags: [\"scope:tool\"] })\n * @example\n * // Check if project has ALL specified tags\n * projectMatchesCriteria(metadata, {\n * tags: [\"scope:tool\", \"type:vanilla\"],\n * tagsMatchMode: \"every\"\n * })\n * @example\n * // Check if project has ANY of the specified tags\n * projectMatchesCriteria(metadata, {\n * tags: [\"scope:tool\", \"scope:client\"],\n * tagsMatchMode: \"some\"\n * })\n * @example\n * // Check if project has specific targets\n * projectMatchesCriteria(metadata, { targets: [\"build\", \"test\"] })\n */\nexport const projectMatchesCriteria = (metadata: ProjectMetadata, criteria: MatchCriteria): boolean => {\n const { tags, targets, tagsMatchMode = \"some\", targetsMatchMode = \"some\" } = criteria;\n\n // Check tags if specified\n if (tags && tags.length > 0) {\n const hasMatchingTags =\n tagsMatchMode === \"every\"\n ? tags.every(tag => metadata.tags.includes(tag))\n : tags.some(tag => metadata.tags.includes(tag));\n\n if (!hasMatchingTags) {\n return false;\n }\n }\n\n // Check targets if specified\n if (targets && targets.length > 0) {\n const hasMatchingTargets =\n targetsMatchMode === \"every\"\n ? targets.every(target => metadata.targets.includes(target))\n : targets.some(target => metadata.targets.includes(target));\n\n if (!hasMatchingTargets) {\n return false;\n }\n }\n\n return true;\n};\n\n/**\n * Clear the metadata cache. Useful for testing.\n */\nexport const clearMetadataCache = (): void => {\n metadataCache.clear();\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"package-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/package-utils.ts"],"names":[],"mappings":";;;;AAAA,+CAAyB;AAiBzB;;;;;;;;;;;;;;;GAeG;AACI,MAAM,eAAe,GAAG,CAAC,eAAuB,EAAE,IAAoB,EAAe,EAAE;IAC5F,MAAM,kBAAkB,GAAG,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACpE,MAAM,WAAW,GAAgB,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAEhE,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,IAAI,EAAE,CAAC;IACpD,MAAM,eAAe,GAAG,WAAW,CAAC,eAAe,IAAI,EAAE,CAAC;IAE1D,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,cAAc;YACjB,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QAC5C,KAAK,iBAAiB;YACpB,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;QAC/C,KAAK,KAAK;YACR,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAClF,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,eAAe,GAAU,IAAI,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,4BAA4B,eAAe,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAnBW,QAAA,eAAe,mBAmB1B;AAEF;;;;;;;;;;;GAWG;AACI,MAAM,wBAAwB,GAAG,CAAC,YAAoB,EAAU,EAAE;IACvE,+DAA+D;IAC/D,IAAI,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACjE,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,mEAAmE;IACnE,IAAI,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACtB,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACnC,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,sDAAsD;IACtD,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7C,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;QACtB,OAAO,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC;AAtBW,QAAA,wBAAwB,4BAsBnC","sourcesContent":["import * as fs from \"fs\";\n\n/**\n * Utility functions for working with package.json and npm packages in ESLint rules.\n *\n * ## Main Functions\n * - `getDependencies()` - Get dependencies of a specific type from package.json\n * - `getPackageNameFromImport()` - Extract base package name from import source\n */\n\nexport type DependencyType = \"dependencies\" | \"devDependencies\" | \"all\";\n\ntype PackageJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n};\n\n/**\n * Get dependencies from package.json based on the specified type.\n *\n * @param packageJsonPath - Absolute path to package.json\n * @param type - Type of dependencies to retrieve\n * @returns Set of package names\n * @example\n * // Get only production dependencies\n * const deps = getDependencies(\"/path/to/package.json\", \"dependencies\");\n * @example\n * // Get only dev dependencies\n * const devDeps = getDependencies(\"/path/to/package.json\", \"devDependencies\");\n * @example\n * // Get all dependencies (union of both)\n * const allDeps = getDependencies(\"/path/to/package.json\", \"all\");\n */\nexport const getDependencies = (packageJsonPath: string, type: DependencyType): Set<string> => {\n const packageJsonContent = fs.readFileSync(packageJsonPath, \"utf8\");\n const packageJson: PackageJson = JSON.parse(packageJsonContent);\n\n const dependencies = packageJson.dependencies ?? {};\n const devDependencies = packageJson.devDependencies ?? {};\n\n switch (type) {\n case \"dependencies\":\n return new Set(Object.keys(dependencies));\n case \"devDependencies\":\n return new Set(Object.keys(devDependencies));\n case \"all\":\n return new Set([...Object.keys(dependencies), ...Object.keys(devDependencies)]);\n default: {\n const exhaustiveCheck: never = type;\n throw new Error(`Unknown dependency type: ${exhaustiveCheck}`);\n }\n }\n};\n\n/**\n * Extract the base package name from an import source.\n * Handles scoped packages and sub-path imports.\n *\n * @param importSource - The import source from an ImportDeclaration node\n * @returns The base package name\n * @example\n * getPackageNameFromImport(\"lodash/fp\") // → \"lodash\"\n * getPackageNameFromImport(\"@scope/package/sub\") // → \"@scope/package\"\n * getPackageNameFromImport(\"react\") // → \"react\"\n * getPackageNameFromImport(\"./relative\") // → \"./relative\" (caller should filter)\n */\nexport const getPackageNameFromImport = (importSource: string): string => {\n // Handle relative imports - return as-is, caller should filter\n if (importSource.startsWith(\".\") || importSource.startsWith(\"/\")) {\n return importSource;\n }\n\n // Handle scoped packages: @scope/package/sub-path → @scope/package\n if (importSource.startsWith(\"@\")) {\n const parts = importSource.split(\"/\");\n if (parts.length >= 2) {\n return `${parts[0]}/${parts[1]}`;\n }\n return importSource;\n }\n\n // Handle regular packages: package/sub-path → package\n const firstSlash = importSource.indexOf(\"/\");\n if (firstSlash !== -1) {\n return importSource.substring(0, firstSlash);\n }\n\n return importSource;\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"typescript-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/typescript-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { MappedOmit } from \"@trackunit/shared-utils\";\nimport { AST_NODE_TYPES, ESLintUtils, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\nimport * as ts from \"typescript\";\n\n// Type guards for TypeScript API\ntype StringLiteralType = ts.Type & { value: string };\ntype EnumLiteralType = ts.Type & { value: string | number };\n\nfunction isStringLiteralType(type: ts.Type): type is StringLiteralType {\n return (type.flags & ts.TypeFlags.StringLiteral) !== 0 && \"value\" in type;\n}\n\nfunction isEnumLiteralType(type: ts.Type): type is EnumLiteralType {\n return (type.flags & ts.TypeFlags.EnumLiteral) !== 0 && \"value\" in type;\n}\n\n// Type guard for TSESTree literal nodes\nfunction isTSLiteralTypeWithStringLiteral(\n node: TSESTree.TypeNode\n): node is TSESTree.TSLiteralType & { literal: TSESTree.Literal & { value: string } } {\n return (\n node.type === AST_NODE_TYPES.TSLiteralType &&\n node.literal.type === AST_NODE_TYPES.Literal &&\n typeof node.literal.value === \"string\"\n );\n}\n\nfunction isTSLiteralTypeWithLiteral(\n node: TSESTree.TypeNode\n): node is TSESTree.TSLiteralType & { literal: TSESTree.Literal } {\n return node.type === AST_NODE_TYPES.TSLiteralType && node.literal.type === AST_NODE_TYPES.Literal;\n}\n\nexport type OptionalProp =\n | { name: string; type: \"boolean\" }\n | { name: string; type: \"string\" }\n | { name: string; type: \"number\" }\n | { name: string; type: \"object\" }\n | { name: string; type: \"stringLiteral\"; stringLiterals: Array<string> }\n | { name: string; type: \"enum\"; enumValues: Array<string | number> }\n | { name: string; type: \"unknown\" };\n\n/**\n * Unified helper function to analyze prop types\n */\nconst analyzeTypeProperties = (\n typeNode: TSESTree.TypeNode | undefined,\n tsType?: ts.Type\n): MappedOmit<OptionalProp, \"name\"> => {\n // Try TypeScript type checker first (more accurate)\n if (tsType) {\n const flags = tsType.getFlags();\n\n // Check for string literal types (including unions like \"a\" | \"b\")\n const isStringLiteral =\n (flags & ts.TypeFlags.StringLiteral) !== 0 ||\n (tsType.isUnion() &&\n tsType.types\n .filter(t => (t.getFlags() & ts.TypeFlags.Undefined) === 0)\n .every(t => (t.getFlags() & ts.TypeFlags.StringLiteral) !== 0) &&\n tsType.types.some(t => (t.getFlags() & ts.TypeFlags.StringLiteral) !== 0));\n\n if (isStringLiteral) {\n let stringLiterals: Array<string>;\n if (tsType.isUnion()) {\n stringLiterals = tsType.types.filter(isStringLiteralType).map(t => t.value);\n } else if (isStringLiteralType(tsType)) {\n stringLiterals = [tsType.value];\n } else {\n stringLiterals = [];\n }\n return { type: \"stringLiteral\", stringLiterals };\n }\n\n // Check for enum types\n if (isEnumLiteralType(tsType)) {\n return { type: \"enum\", enumValues: [tsType.value] };\n } else if (tsType.isUnion()) {\n const enumTypes = tsType.types.filter(isEnumLiteralType);\n if (enumTypes.length > 0) {\n const enumValues = enumTypes.map(t => t.value);\n return { type: \"enum\", enumValues };\n }\n }\n\n // Check for union types that contain specific primitives (e.g., boolean | undefined)\n if (tsType.isUnion()) {\n const nonUndefinedTypes = tsType.types.filter(t => (t.getFlags() & ts.TypeFlags.Undefined) === 0);\n\n // Check if all non-undefined types are booleans\n if (\n nonUndefinedTypes.length > 0 &&\n nonUndefinedTypes.every(\n t => (t.getFlags() & ts.TypeFlags.Boolean) !== 0 || (t.getFlags() & ts.TypeFlags.BooleanLiteral) !== 0\n )\n ) {\n return { type: \"boolean\" };\n }\n\n // Check if all non-undefined types are strings\n if (nonUndefinedTypes.length > 0 && nonUndefinedTypes.every(t => (t.getFlags() & ts.TypeFlags.String) !== 0)) {\n return { type: \"string\" };\n }\n\n // Check if all non-undefined types are numbers\n if (\n nonUndefinedTypes.length > 0 &&\n nonUndefinedTypes.every(\n t => (t.getFlags() & ts.TypeFlags.Number) !== 0 || (t.getFlags() & ts.TypeFlags.NumberLiteral) !== 0\n )\n ) {\n return { type: \"number\" };\n }\n }\n\n // Check for other primitive types\n if ((flags & ts.TypeFlags.Boolean) !== 0 || (flags & ts.TypeFlags.BooleanLiteral) !== 0) {\n return { type: \"boolean\" };\n }\n if ((flags & ts.TypeFlags.String) !== 0) {\n return { type: \"string\" };\n }\n if ((flags & ts.TypeFlags.Number) !== 0 || (flags & ts.TypeFlags.NumberLiteral) !== 0) {\n return { type: \"number\" };\n }\n if ((flags & ts.TypeFlags.Object) !== 0) {\n return { type: \"object\" };\n }\n\n // If we couldn't identify the type, mark it as unknown\n return { type: \"unknown\" };\n }\n\n // Fallback to AST-based analysis\n if (!typeNode) {\n return { type: \"unknown\" };\n }\n\n // Check for string literal types\n const isStringLiteralAST =\n isTSLiteralTypeWithStringLiteral(typeNode) ||\n (typeNode.type === AST_NODE_TYPES.TSUnionType && typeNode.types.every(isTSLiteralTypeWithStringLiteral));\n\n if (isStringLiteralAST) {\n let stringLiterals: Array<string>;\n if (typeNode.type === AST_NODE_TYPES.TSUnionType) {\n stringLiterals = typeNode.types.filter(isTSLiteralTypeWithStringLiteral).map(t => t.literal.value);\n } else if (isTSLiteralTypeWithStringLiteral(typeNode)) {\n stringLiterals = [typeNode.literal.value];\n } else {\n stringLiterals = [];\n }\n return { type: \"stringLiteral\", stringLiterals };\n }\n\n // Check for enum types (AST-based approximation)\n if (\n typeNode.type === AST_NODE_TYPES.TSUnionType &&\n typeNode.types.every(\n t =>\n t.type === AST_NODE_TYPES.TSLiteralType &&\n t.literal.type === AST_NODE_TYPES.Literal &&\n (typeof t.literal.value === \"string\" || typeof t.literal.value === \"number\")\n )\n ) {\n const enumValues = typeNode.types\n .filter(isTSLiteralTypeWithLiteral)\n .map(t => t.literal.value)\n .filter((value): value is string | number => typeof value === \"string\" || typeof value === \"number\");\n return { type: \"enum\", enumValues };\n }\n\n // Check for other primitive types\n if (\n typeNode.type === AST_NODE_TYPES.TSBooleanKeyword ||\n (typeNode.type === AST_NODE_TYPES.TSLiteralType &&\n typeNode.literal.type === AST_NODE_TYPES.Literal &&\n typeof typeNode.literal.value === \"boolean\")\n ) {\n return { type: \"boolean\" };\n }\n\n if (typeNode.type === AST_NODE_TYPES.TSStringKeyword) {\n return { type: \"string\" };\n }\n\n if (\n typeNode.type === AST_NODE_TYPES.TSNumberKeyword ||\n (typeNode.type === AST_NODE_TYPES.TSLiteralType &&\n typeNode.literal.type === AST_NODE_TYPES.Literal &&\n typeof typeNode.literal.value === \"number\")\n ) {\n return { type: \"number\" };\n }\n\n if (\n typeNode.type === AST_NODE_TYPES.TSTypeLiteral ||\n typeNode.type === AST_NODE_TYPES.TSArrayType ||\n (typeNode.type === AST_NODE_TYPES.TSTypeReference &&\n typeNode.typeName.type === AST_NODE_TYPES.Identifier &&\n /^(Array|Object|Record|Map|Set)$/.test(typeNode.typeName.name))\n ) {\n return { type: \"object\" };\n }\n\n return { type: \"unknown\" };\n};\n\n/**\n * Helper function to extract optional properties from a TypeScript type annotation\n */\nexport const getOptionalPropsFromType = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n typeNode: TSESTree.TypeNode | undefined\n): Array<OptionalProp> => {\n if (!typeNode) return [];\n\n const optionalProps: Array<OptionalProp> = [];\n\n const processType = (node: TSESTree.TypeNode) => {\n if (node.type === AST_NODE_TYPES.TSTypeReference && node.typeName.type === AST_NODE_TYPES.Identifier) {\n // Try to get type information using the type checker\n const services = ESLintUtils.getParserServices(context);\n\n try {\n const checker = services.program.getTypeChecker();\n const tsNode = services.esTreeNodeToTSNodeMap.get(node);\n const type = checker.getTypeFromTypeNode(tsNode);\n\n // Get the symbol properties - this works for resolved intersection types\n const props = checker.getPropertiesOfType(type);\n props.forEach(prop => {\n const propType = checker.getTypeOfSymbolAtLocation(prop, tsNode);\n\n // Check if the property is optional by examining all declarations\n const isOptional =\n prop.declarations?.some(decl => \"questionToken\" in decl && decl.questionToken !== undefined) ?? false;\n\n if (isOptional) {\n const typeAnalysis = analyzeTypeProperties(undefined, propType);\n optionalProps.push({\n name: prop.getName(),\n ...typeAnalysis,\n });\n }\n });\n } catch (_error) {\n // If type checking fails, fall back to the original behavior\n return;\n }\n\n return;\n }\n\n if (node.type === AST_NODE_TYPES.TSTypeLiteral) {\n node.members.forEach(member => {\n if (\n member.type === AST_NODE_TYPES.TSPropertySignature &&\n member.key.type === AST_NODE_TYPES.Identifier &&\n member.optional\n ) {\n const propName = member.key.name;\n const propType = member.typeAnnotation?.typeAnnotation;\n\n const typeAnalysis = analyzeTypeProperties(propType);\n optionalProps.push({\n name: propName,\n ...typeAnalysis,\n });\n }\n });\n }\n\n if (node.type === AST_NODE_TYPES.TSIntersectionType) {\n node.types.forEach(processType);\n }\n\n if (node.type === AST_NODE_TYPES.TSUnionType) {\n // For union types, we'll be conservative and process all types\n node.types.forEach(processType);\n }\n };\n\n processType(typeNode);\n return optionalProps;\n};\n"]}
|