@trackunit/eslint-plugin-trackunit 0.0.3 → 0.0.4

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 (50) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/package.json +1 -1
  3. package/src/index.js.map +0 -1
  4. package/src/lib/config/fragments/ignores.js.map +0 -1
  5. package/src/lib/config/fragments/import-rules.js.map +0 -1
  6. package/src/lib/config/fragments/jest-overrides.js.map +0 -1
  7. package/src/lib/config/fragments/jsdoc-rules.js.map +0 -1
  8. package/src/lib/config/fragments/module-boundaries.js.map +0 -1
  9. package/src/lib/config/fragments/react-rules.js.map +0 -1
  10. package/src/lib/config/fragments/restricted-imports.js.map +0 -1
  11. package/src/lib/config/fragments/testing-library.js.map +0 -1
  12. package/src/lib/config/fragments/typescript-rules.js.map +0 -1
  13. package/src/lib/config/index.js.map +0 -1
  14. package/src/lib/config/plugins.js.map +0 -1
  15. package/src/lib/config/presets/base.js.map +0 -1
  16. package/src/lib/config/presets/e2e.js.map +0 -1
  17. package/src/lib/config/presets/public-api.js.map +0 -1
  18. package/src/lib/config/presets/react.js.map +0 -1
  19. package/src/lib/config/presets/server.js.map +0 -1
  20. package/src/lib/config/utils.js.map +0 -1
  21. package/src/lib/config-helpers/create-skip-when.js.map +0 -1
  22. package/src/lib/rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array.js.map +0 -1
  23. package/src/lib/rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match.js.map +0 -1
  24. package/src/lib/rules/no-internal-barrel-files/examples.js.map +0 -1
  25. package/src/lib/rules/no-internal-barrel-files/no-internal-barrel-files.js.map +0 -1
  26. package/src/lib/rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public.js.map +0 -1
  27. package/src/lib/rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks.js.map +0 -1
  28. package/src/lib/rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop.js.map +0 -1
  29. package/src/lib/rules/no-typescript-assertion/examples.js.map +0 -1
  30. package/src/lib/rules/no-typescript-assertion/no-typescript-assertion.js.map +0 -1
  31. package/src/lib/rules/prefer-destructured-imports/prefer-destructured-imports.js.map +0 -1
  32. package/src/lib/rules/prefer-event-specific-callback-naming/name-suggestion-strategies.js.map +0 -1
  33. package/src/lib/rules/prefer-event-specific-callback-naming/prefer-event-specific-callback-naming.js.map +0 -1
  34. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/string-based.js.map +0 -1
  35. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/type-based.js.map +0 -1
  36. package/src/lib/rules/prefer-event-specific-callback-naming/utils.js.map +0 -1
  37. package/src/lib/rules/prefer-field-components/prefer-field-components.js.map +0 -1
  38. package/src/lib/rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props.js.map +0 -1
  39. package/src/lib/rules/require-classname-alternatives/require-classname-alternatives.js.map +0 -1
  40. package/src/lib/rules/require-list-item-virtualization-props/require-list-item-virtualization-props.js.map +0 -1
  41. package/src/lib/rules/require-optional-prop-initialization/require-optional-prop-initialization.js.map +0 -1
  42. package/src/lib/rules/require-optional-prop-initialization/suggestion-utils.js.map +0 -1
  43. package/src/lib/rules-map.js.map +0 -1
  44. package/src/lib/utils/ast-utils.js.map +0 -1
  45. package/src/lib/utils/classname-utils.js.map +0 -1
  46. package/src/lib/utils/file-utils.js.map +0 -1
  47. package/src/lib/utils/import-utils.js.map +0 -1
  48. package/src/lib/utils/nx-utils.js.map +0 -1
  49. package/src/lib/utils/package-utils.js.map +0 -1
  50. package/src/lib/utils/typescript-utils.js.map +0 -1
@@ -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"]}