@trackunit/eslint-plugin-trackunit 0.6.107 → 0.6.109

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 (61) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/migrations/entry.js.map +1 -0
  3. package/package.json +1 -1
  4. package/src/index.js.map +1 -0
  5. package/src/lib/config/fragments/ignores.js.map +1 -0
  6. package/src/lib/config/fragments/import-rules.js.map +1 -0
  7. package/src/lib/config/fragments/jest-overrides.js.map +1 -0
  8. package/src/lib/config/fragments/jsdoc-rules.js.map +1 -0
  9. package/src/lib/config/fragments/module-boundaries.js.map +1 -0
  10. package/src/lib/config/fragments/no-direct-storage-access.js.map +1 -0
  11. package/src/lib/config/fragments/react-rules.js.map +1 -0
  12. package/src/lib/config/fragments/restricted-imports.js.map +1 -0
  13. package/src/lib/config/fragments/testing-library.js.map +1 -0
  14. package/src/lib/config/fragments/typescript-rules.js.map +1 -0
  15. package/src/lib/config/index.js.map +1 -0
  16. package/src/lib/config/plugins.js.map +1 -0
  17. package/src/lib/config/presets/base.js.map +1 -0
  18. package/src/lib/config/presets/e2e.js.map +1 -0
  19. package/src/lib/config/presets/react.js.map +1 -0
  20. package/src/lib/config/presets/server.js.map +1 -0
  21. package/src/lib/config/utils.js.map +1 -0
  22. package/src/lib/config-helpers/create-skip-when.js.map +1 -0
  23. package/src/lib/rules/component-name-matches-filename/component-name-matches-filename.js.map +1 -0
  24. package/src/lib/rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array.js.map +1 -0
  25. package/src/lib/rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match.js.map +1 -0
  26. package/src/lib/rules/no-deprecated-graphql-fields/no-deprecated-graphql-fields.js.map +1 -0
  27. package/src/lib/rules/no-deprecated-graphql-fields/schema-cache.js.map +1 -0
  28. package/src/lib/rules/no-dynamic-translation-key/no-dynamic-translation-key.js.map +1 -0
  29. package/src/lib/rules/no-internal-barrel-files/no-internal-barrel-files.js.map +1 -0
  30. package/src/lib/rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public.js.map +1 -0
  31. package/src/lib/rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks.js.map +1 -0
  32. package/src/lib/rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop.js.map +1 -0
  33. package/src/lib/rules/no-typescript-assertion/no-typescript-assertion.js.map +1 -0
  34. package/src/lib/rules/no-unused-translation-key/expand-dynamic-key.js.map +1 -0
  35. package/src/lib/rules/no-unused-translation-key/no-unused-translation-key.js.map +1 -0
  36. package/src/lib/rules/no-unused-translation-key/used-strings.js.map +1 -0
  37. package/src/lib/rules/one-component-per-file/one-component-per-file.js.map +1 -0
  38. package/src/lib/rules/prefer-destructured-imports/prefer-destructured-imports.js.map +1 -0
  39. package/src/lib/rules/prefer-event-specific-callback-naming/name-suggestion-strategies.js.map +1 -0
  40. package/src/lib/rules/prefer-event-specific-callback-naming/prefer-event-specific-callback-naming.js.map +1 -0
  41. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/string-based.js.map +1 -0
  42. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/type-based.js.map +1 -0
  43. package/src/lib/rules/prefer-event-specific-callback-naming/utils.js.map +1 -0
  44. package/src/lib/rules/prefer-field-components/prefer-field-components.js.map +1 -0
  45. package/src/lib/rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props.js.map +1 -0
  46. package/src/lib/rules/require-classname-alternatives/require-classname-alternatives.js.map +1 -0
  47. package/src/lib/rules/require-component-prop-contracts/require-component-prop-contracts.js.map +1 -0
  48. package/src/lib/rules/require-list-item-virtualization-props/require-list-item-virtualization-props.js.map +1 -0
  49. package/src/lib/rules/require-optional-prop-initialization/require-optional-prop-initialization.js.map +1 -0
  50. package/src/lib/rules/require-optional-prop-initialization/suggestion-utils.js.map +1 -0
  51. package/src/lib/rules/require-storybook-folder-landing-page/require-storybook-folder-landing-page.js.map +1 -0
  52. package/src/lib/rules-map.js.map +1 -0
  53. package/src/lib/utils/ast-utils.js.map +1 -0
  54. package/src/lib/utils/component-utils.js.map +1 -0
  55. package/src/lib/utils/file-utils.js.map +1 -0
  56. package/src/lib/utils/import-utils.js.map +1 -0
  57. package/src/lib/utils/nx-utils.js.map +1 -0
  58. package/src/lib/utils/package-utils.js.map +1 -0
  59. package/src/lib/utils/program-utils.js.map +1 -0
  60. package/src/lib/utils/translation-key-types.js.map +1 -0
  61. package/src/lib/utils/typescript-utils.js.map +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-list-item-virtualization-props.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/require-list-item-virtualization-props/require-list-item-virtualization-props.ts"],"names":[],"mappings":";;;AAAA,oDAA2F;AAE3F,MAAM,UAAU,GAAG,mBAAW,CAAC,WAAW,CACxC,IAAI,CAAC,EAAE,CAAC,6FAA6F,IAAI,KAAK,CAC/G,CAAC;AAcF;;GAEG;AACH,MAAM,qBAAqB,GAAG,CAAC,QAA6B,EAAW,EAAE;IACvE,wCAAwC;IACxC,IAAI,QAAQ,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;QAChD,OAAO,QAAQ,CAAC,IAAI,KAAK,eAAe,IAAI,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAClF,CAAC;IAED,+CAA+C;IAC/C,IAAI,QAAQ,CAAC,IAAI,KAAK,sBAAc,CAAC,gBAAgB,EAAE,CAAC;QACtD,iFAAiF;QACjF,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,EAAE,CAAC;YAC/E,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC5C,IAAI,YAAY,KAAK,eAAe,IAAI,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC3E,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,8BAA8B,GAAG,CACrC,OAA4B,EAC5B,OAA6D,EACpD,EAAE;IACX,2FAA2F;IAC3F,MAAM,aAAa,GAAG,CAAC,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;IAErE,MAAM,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC;IACrD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,IAAI,sBAAsB,GAAG,KAAK,CAAC;IAEnC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,aAAa,EAAE,CAAC;YACjG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,kBAAkB,EAAE,CAAC;YAC3D,8CAA8C;YAC9C,IAAI,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACzC,sBAAsB,GAAG,IAAI,CAAC;YAChC,CAAC;iBAAM,CAAC;gBACN,qDAAqD;gBACrD,iEAAiE;gBACjE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC7D,MAAM,gBAAgB,GAAG,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;gBAC9D,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBACtD,IAAI,gBAAgB,IAAI,YAAY,EAAE,CAAC;oBACrC,sBAAsB,GAAG,IAAI,CAAC;gBAChC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,IAAI,sBAAsB,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,0CAA0C;IAC1C,OAAO,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1D,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,iBAAiB,GAAG,CAAC,OAAsB,EAAE,IAAY,EAAW,EAAE,CAC1E,OAAO,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU;IAC1C,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,aAAa;IACjE,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;AAE5C;;GAEG;AACH,MAAM,0BAA0B,GAAG,CAAC,IAAmB,EAAW,EAAE;IAClE,IAAI,OAAO,GAA8B,IAAI,CAAC,MAAM,CAAC;IAErD,OAAO,OAAO,EAAE,CAAC;QACf,oCAAoC;QACpC,IAAI,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;YACvC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,wFAAwF;QACxF,6FAA6F;QAC7F,wFAAwF;QACxF,6FAA6F;QAC7F,yFAAyF;QACzF,4EAA4E;QAC5E,IAAI,OAAO,CAAC,IAAI,KAAK,sBAAc,CAAC,YAAY,EAAE,CAAC;YACjD,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;YAC5C,IAAI,CAAC,iBAAiB,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,CAAC;gBAC9C,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,iBAAiB,GAAG,CAAC,OAA4B,EAAW,EAAE;IAClE,+EAA+E;IAC/E,MAAM,OAAO,GAA8B,OAAO,CAAC,MAAM,CAAC;IAE1D,gFAAgF;IAChF,2FAA2F;IAE3F,0DAA0D;IAC1D,IAAI,OAAO,CAAC,IAAI,KAAK,sBAAc,CAAC,eAAe,EAAE,CAAC;QACpD,OAAO,0BAA0B,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED,iFAAiF;IACjF,IAAI,OAAO,CAAC,IAAI,KAAK,sBAAc,CAAC,uBAAuB,EAAE,CAAC;QAC5D,OAAO,0BAA0B,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED,8DAA8D;IAC9D,IAAI,OAAO,CAAC,IAAI,KAAK,sBAAc,CAAC,qBAAqB,EAAE,CAAC;QAC1D,8EAA8E;QAC9E,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;QACzC,IACE,iBAAiB,CAAC,IAAI,KAAK,sBAAc,CAAC,eAAe;YACzD,iBAAiB,CAAC,IAAI,KAAK,sBAAc,CAAC,uBAAuB,EACjE,CAAC;YACD,OAAO,0BAA0B,CAAC,iBAAiB,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,iBAAiB,GAAG,CAAC,OAA4B,EAAiB,EAAE;IACxE,IAAI,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,aAAa,EAAE,CAAC;QACtE,OAAO,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,kBAAkB,GAAG,CAAC,WAAmB,EAAW,EAAE;IAC1D,OAAO,WAAW,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC;AAC5C,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,aAAa,GAAG,CAAC,WAAmB,EAAW,EAAE;IACrD,qEAAqE;IACrE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,SAAS,KAAK,SAAS,CAAC,WAAW,EAAE,CAAC;AAC/C,CAAC,CAAC;AAEW,QAAA,kCAAkC,GAAG,UAAU,CAAsB;IAChF,IAAI,EAAE,wCAAwC;IAC9C,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,sEAAsE;SACpF;QACD,cAAc,EAAE,IAAI;QACpB,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,qBAAqB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;iBAC3C;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;QACD,QAAQ,EAAE;YACR,0BAA0B,EACxB,wEAAwE;gBACxE,2FAA2F;YAC7F,mBAAmB,EAAE,2CAA2C;YAChE,mBAAmB,EACjB,0EAA0E;gBAC1E,6EAA6E;SAChF;KACF;IACD,cAAc,EAAE;QACd;YACE,qBAAqB,EAAE,IAAI;SAC5B;KACF;IACD,MAAM,CAAC,OAAO,EAAE,OAAO;QACrB,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAE1B,OAAO;YACL,UAAU,CAAC,IAAyB;gBAClC,4CAA4C;gBAC5C,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7B,OAAO;gBACT,CAAC;gBAED,MAAM,WAAW,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAC5C,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,OAAO;gBACT,CAAC;gBAED,iDAAiD;gBACjD,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC/B,iDAAiD;oBACjD,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC;wBACrC,OAAO,CAAC,MAAM,CAAC;4BACb,IAAI,EAAE,IAAI,CAAC,cAAc;4BACzB,SAAS,EAAE,qBAAqB;4BAChC,IAAI,EAAE,EAAE,WAAW,EAAE;yBACtB,CAAC,CAAC;wBACH,OAAO;oBACT,CAAC;oBAED,kDAAkD;oBAClD,IAAI,CAAC,8BAA8B,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;wBACnD,OAAO,CAAC,MAAM,CAAC;4BACb,IAAI,EAAE,IAAI,CAAC,cAAc;4BACzB,SAAS,EAAE,4BAA4B;4BACvC,IAAI,EAAE,EAAE,WAAW,EAAE;4BACrB,OAAO,EAAE;gCACP;oCACE,SAAS,EAAE,qBAAqB;oCAChC,GAAG,CAAC,KAAK;wCACP,gDAAgD;wCAChD,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC;wCACvC,MAAM,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;wCAE3C,IAAI,SAAS,EAAE,CAAC;4CACd,OAAO,KAAK,CAAC,gBAAgB,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;wCAClE,CAAC;6CAAM,CAAC;4CACN,gCAAgC;4CAChC,OAAO,KAAK,CAAC,eAAe,CAAC,UAAU,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;wCACvE,CAAC;oCACH,CAAC;iCACF;6BACF;yBACF,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,6DAA6D;oBAC7D,IAAI,MAAM,CAAC,qBAAqB,KAAK,KAAK,IAAI,CAAC,8BAA8B,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;wBAC7F,OAAO,CAAC,MAAM,CAAC;4BACb,IAAI,EAAE,IAAI,CAAC,cAAc;4BACzB,SAAS,EAAE,4BAA4B;4BACvC,IAAI,EAAE,EAAE,WAAW,EAAE;4BACrB,OAAO,EAAE;gCACP;oCACE,SAAS,EAAE,qBAAqB;oCAChC,GAAG,CAAC,KAAK;wCACP,gDAAgD;wCAChD,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC;wCACvC,MAAM,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;wCAE3C,IAAI,SAAS,EAAE,CAAC;4CACd,OAAO,KAAK,CAAC,gBAAgB,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;wCAClE,CAAC;6CAAM,CAAC;4CACN,gCAAgC;4CAChC,OAAO,KAAK,CAAC,eAAe,CAAC,UAAU,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;wCACvE,CAAC;oCACH,CAAC;iCACF;6BACF;yBACF,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["import { AST_NODE_TYPES, ESLintUtils, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}.ts`\n);\n\ntype Options = [\n {\n /**\n * Whether to allow custom components that extend VirtualizationListItemProps\n * instead of requiring explicit spreading of listItemProps\n */\n allowCustomComponents?: boolean;\n },\n];\n\ntype MessageIds = \"requireVirtualizationProps\" | \"spreadListItemProps\" | \"useSemanticListItem\";\n\n/**\n * Check if a spread attribute argument contains listItemProps\n */\nconst isListItemPropsSpread = (argument: TSESTree.Expression): boolean => {\n // Direct identifier: {...listItemProps}\n if (argument.type === AST_NODE_TYPES.Identifier) {\n return argument.name === \"listItemProps\" || argument.name.includes(\"ItemProps\");\n }\n\n // Member expression: {...params.listItemProps}\n if (argument.type === AST_NODE_TYPES.MemberExpression) {\n // Check if property is an identifier (not computed like params[\"listItemProps\"])\n if (!argument.computed && argument.property.type === AST_NODE_TYPES.Identifier) {\n const propertyName = argument.property.name;\n if (propertyName === \"listItemProps\" || propertyName.includes(\"ItemProps\")) {\n return true;\n }\n }\n }\n\n return false;\n};\n\n/**\n * Check if a JSX element has the required virtualization props\n */\nconst hasRequiredVirtualizationProps = (\n element: TSESTree.JSXElement,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): boolean => {\n // ref is functionally required for virtualization even though TypeScript marks it optional\n const requiredProps = [\"className\", \"data-index\", \"tabIndex\", \"ref\"];\n\n const attributes = element.openingElement.attributes;\n const propNames = new Set<string>();\n let hasSpreadListItemProps = false;\n\n for (const attr of attributes) {\n if (attr.type === AST_NODE_TYPES.JSXAttribute && attr.name.type === AST_NODE_TYPES.JSXIdentifier) {\n propNames.add(attr.name.name);\n } else if (attr.type === AST_NODE_TYPES.JSXSpreadAttribute) {\n // Check if spreading listItemProps or similar\n if (isListItemPropsSpread(attr.argument)) {\n hasSpreadListItemProps = true;\n } else {\n // Fallback: check source code text for listItemProps\n // This handles edge cases where AST structure might be different\n const sourceCode = context.sourceCode.getText(attr.argument);\n const hasListItemProps = sourceCode.includes(\"listItemProps\");\n const hasItemProps = sourceCode.includes(\"ItemProps\");\n if (hasListItemProps || hasItemProps) {\n hasSpreadListItemProps = true;\n }\n }\n }\n }\n\n // If spreading listItemProps, assume it has all required props\n if (hasSpreadListItemProps) {\n return true;\n }\n\n // Check if all required props are present\n return requiredProps.every(prop => propNames.has(prop));\n};\n\n/**\n * Check if a JSXElement is opened with the given tag name\n */\nconst isJSXElementNamed = (element: TSESTree.Node, name: string): boolean =>\n element.type === AST_NODE_TYPES.JSXElement &&\n element.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier &&\n element.openingElement.name.name === name;\n\n/**\n * Check if we're inside a List component's render function\n */\nconst isInsideListRenderFunction = (node: TSESTree.Node): boolean => {\n let current: TSESTree.Node | undefined = node.parent;\n\n while (current) {\n // Look for JSX element named \"List\"\n if (isJSXElementNamed(current, \"List\")) {\n return true;\n }\n\n // Once the walk enters a JSX attribute value, we've left the \"rendered output\" path and\n // stepped into some element's prop (e.g. a Tooltip's `label` or a ListItem's `description`).\n // Only keep walking if that attribute belongs to the <List> itself (e.g. its `children`\n // render-prop is authored as an explicit attribute rather than JSX children) - otherwise any\n // unrelated <li> nested arbitrarily deep inside a row's props (tooltip content, a nested\n // list, ...) would be misidentified as the row's own virtualized list item.\n if (current.type === AST_NODE_TYPES.JSXAttribute) {\n const owningElement = current.parent.parent;\n if (!isJSXElementNamed(owningElement, \"List\")) {\n return false;\n }\n }\n\n current = current.parent;\n }\n\n return false;\n};\n\n/**\n * Check if a JSX element is a direct list item (directly returned from List render function)\n */\nconst isListItemElement = (element: TSESTree.JSXElement): boolean => {\n // Check if this element is the direct return value from a List render function\n const current: TSESTree.Node | undefined = element.parent;\n\n // We need to find if this element is DIRECTLY returned from the render function\n // This means it should be the immediate child of a return statement or arrow function body\n\n // Case 1: Direct return statement - return (<li>...</li>)\n if (current.type === AST_NODE_TYPES.ReturnStatement) {\n return isInsideListRenderFunction(current);\n }\n\n // Case 2: Arrow function body - ({ key, listItemProps, item }) => (<li>...</li>)\n if (current.type === AST_NODE_TYPES.ArrowFunctionExpression) {\n return isInsideListRenderFunction(current);\n }\n\n // Case 3: Conditional expression - item ? <li>...</li> : null\n if (current.type === AST_NODE_TYPES.ConditionalExpression) {\n // Check if the conditional is directly returned or is the arrow function body\n const conditionalParent = current.parent;\n if (\n conditionalParent.type === AST_NODE_TYPES.ReturnStatement ||\n conditionalParent.type === AST_NODE_TYPES.ArrowFunctionExpression\n ) {\n return isInsideListRenderFunction(conditionalParent);\n }\n }\n\n return false;\n};\n\n/**\n * Get the name of a JSX element\n */\nconst getJSXElementName = (element: TSESTree.JSXElement): string | null => {\n if (element.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier) {\n return element.openingElement.name.name;\n }\n return null;\n};\n\n/**\n * Check if element is a semantic list item element\n */\nconst isSemanticListItem = (elementName: string): boolean => {\n return elementName.toLowerCase() === \"li\";\n};\n\n/**\n * Check if element name is a built-in HTML element (vs custom React component)\n */\nconst isHTMLElement = (elementName: string): boolean => {\n // HTML elements are lowercase, React components start with uppercase\n if (elementName.length === 0) {\n return false;\n }\n const firstChar = elementName[0];\n if (!firstChar) {\n return false;\n }\n return firstChar === firstChar.toLowerCase();\n};\n\nexport const requireListItemVirtualizationProps = createRule<Options, MessageIds>({\n name: \"require-list-item-virtualization-props\",\n meta: {\n type: \"problem\",\n docs: {\n description: \"Require list items within <List> to have VirtualizationListItemProps\",\n },\n hasSuggestions: true,\n schema: [\n {\n type: \"object\",\n properties: {\n allowCustomComponents: { type: \"boolean\" },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n requireVirtualizationProps:\n \"List item '{{elementName}}' must include VirtualizationListItemProps. \" +\n \"Spread {...listItemProps} or manually specify className, data-index, tabIndex, ref props.\",\n spreadListItemProps: \"Spread {...listItemProps} on this element\",\n useSemanticListItem:\n \"Use semantic <li> elements for list items instead of '{{elementName}}'. \" +\n \"List items should be <li> elements with proper VirtualizationListItemProps.\",\n },\n },\n defaultOptions: [\n {\n allowCustomComponents: true,\n },\n ],\n create(context, options) {\n const config = options[0];\n\n return {\n JSXElement(node: TSESTree.JSXElement) {\n // Skip if not inside a List render function\n if (!isListItemElement(node)) {\n return;\n }\n\n const elementName = getJSXElementName(node);\n if (!elementName) {\n return;\n }\n\n // Check element type and apply appropriate rules\n if (isHTMLElement(elementName)) {\n // For HTML elements, enforce semantic list items\n if (!isSemanticListItem(elementName)) {\n context.report({\n node: node.openingElement,\n messageId: \"useSemanticListItem\",\n data: { elementName },\n });\n return;\n }\n\n // For <li> elements, require virtualization props\n if (!hasRequiredVirtualizationProps(node, context)) {\n context.report({\n node: node.openingElement,\n messageId: \"requireVirtualizationProps\",\n data: { elementName },\n suggest: [\n {\n messageId: \"spreadListItemProps\",\n fix(fixer) {\n // Add {...listItemProps} as the first attribute\n const openingTag = node.openingElement;\n const firstAttr = openingTag.attributes[0];\n\n if (firstAttr) {\n return fixer.insertTextBefore(firstAttr, \"{...listItemProps} \");\n } else {\n // Insert after the element name\n return fixer.insertTextAfter(openingTag.name, \" {...listItemProps}\");\n }\n },\n },\n ],\n });\n }\n } else {\n // For custom components, check allowCustomComponents setting\n if (config.allowCustomComponents === false && !hasRequiredVirtualizationProps(node, context)) {\n context.report({\n node: node.openingElement,\n messageId: \"requireVirtualizationProps\",\n data: { elementName },\n suggest: [\n {\n messageId: \"spreadListItemProps\",\n fix(fixer) {\n // Add {...listItemProps} as the first attribute\n const openingTag = node.openingElement;\n const firstAttr = openingTag.attributes[0];\n\n if (firstAttr) {\n return fixer.insertTextBefore(firstAttr, \"{...listItemProps} \");\n } else {\n // Insert after the element name\n return fixer.insertTextAfter(openingTag.name, \" {...listItemProps}\");\n }\n },\n },\n ],\n });\n }\n }\n },\n };\n },\n});\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-optional-prop-initialization.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/require-optional-prop-initialization/require-optional-prop-initialization.ts"],"names":[],"mappings":";;;AAAA,oDAAiF;AACjF,qDAO+B;AAC/B,mEAAwE;AACxE,yDAA0E;AAE1E,MAAM,UAAU,GAAG,mBAAW,CAAC,WAAW,CACxC,IAAI,CAAC,EAAE,CAAC,6FAA6F,IAAI,KAAK,CAC/G,CAAC;AAcW,QAAA,iCAAiC,GAAG,UAAU,CAAsB;IAC/E,IAAI,EAAE,sCAAsC;IAC5C,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EAAE,yEAAyE;SACvF;QACD,cAAc,EAAE,IAAI;QACpB,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,mBAAmB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;oBACxC,oBAAoB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;oBACzC,mBAAmB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;oBACxC,mBAAmB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;oBACxC,iBAAiB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;oBACtC,+BAA+B,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;oBACpD,oBAAoB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;iBAC1C;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;QACD,QAAQ,EAAE;YACR,qBAAqB,EAAE,oDAAoD;YAC3E,cAAc,EAAE,iBAAiB;SAClC;KACF;IACD,cAAc,EAAE;QACd;YACE,mBAAmB,EAAE,IAAI;YACzB,oBAAoB,EAAE,KAAK;YAC3B,mBAAmB,EAAE,IAAI;YACzB,mBAAmB,EAAE,IAAI;YACzB,iBAAiB,EAAE,KAAK;YACxB,+BAA+B,EAAE,KAAK;YACtC,oBAAoB,EAAE,IAAI;SAC3B;KACF;IACD,MAAM,CAAC,OAAO,EAAE,OAAO;QACrB,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAE1B,2CAA2C;QAC3C,MAAM,mBAAmB,GAAG,CAC1B,YAA6E,EAC7E,UAA0C,EAC1C,EAAE;YACF,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO;YACT,CAAC;YAED,IAAI,cAA6C,CAAC;YAElD,oGAAoG;YACpG,IAAI,UAAU,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,UAAU,CAAC,IAAI,KAAK,sBAAc,CAAC,aAAa,EAAE,CAAC;gBACtG,cAAc,GAAG,UAAU,CAAC,cAAc,EAAE,cAAc,CAAC;YAC7D,CAAC;iBAAM,CAAC;gBACN,OAAO;YACT,CAAC;YAED,MAAM,aAAa,GAAG,IAAA,2CAAwB,EAAC,OAAO,EAAE,cAAc,CAAC,CAAC;YAExE,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/B,OAAO;YACT,CAAC;YAED,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAE5G,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;gBAC3B,2EAA2E;gBAC3E,MAAM,SAAS,GACb,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,mBAAmB,KAAK,IAAI,CAAC;oBAC/D,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,oBAAoB,KAAK,IAAI,CAAC;oBACjE,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,mBAAmB,KAAK,IAAI,CAAC;oBAC/D,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,mBAAmB,KAAK,IAAI,CAAC;oBAC/D,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,iBAAiB,KAAK,IAAI,CAAC;oBAC3D,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,MAAM,CAAC,+BAA+B,KAAK,IAAI,CAAC;oBAClF,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,6BAA6B;gBAExD,IAAI,SAAS,EAAE,CAAC;oBACd,OAAO;gBACT,CAAC;gBAED,wDAAwD;gBACxD,IAAI,MAAM,CAAC,oBAAoB,KAAK,IAAI,IAAI,CAAC,IAAA,qCAAyB,EAAC,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACzG,OAAO;gBACT,CAAC;gBAED,0GAA0G;gBAC1G,+EAA+E;gBAC/E,IACE,CAAC,IAAA,6CAAiC,EAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;oBACzD,CAAC,IAAA,qCAAyB,EAAC,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,EAC5D,CAAC;oBACD,OAAO;gBACT,CAAC;gBAED,sGAAsG;gBACtG,IAAI,IAAA,oCAAwB,EAAC,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;oBACxE,OAAO;gBACT,CAAC;gBAED,8EAA8E;gBAC9E,IAAI,CAAC,IAAA,kCAAsB,EAAC,YAAY,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC;oBACjE,MAAM,mBAAmB,GAAG,UAAU,CAAC,IAAI,KAAK,sBAAc,CAAC,aAAa,CAAC;oBAC7E,MAAM,YAAY,GAAG,IAAA,0CAA8B,EAAC,YAAY,CAAC,CAAC;oBAClE,MAAM,cAAc,GAAG,UAAU,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;oBAEjG,MAAM,WAAW,GAAG,IAAA,sCAAmB,EACrC,IAAI,EACJ,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,OAAO,CACR,CAAC;oBAEF,6DAA6D;oBAC7D,IAAI,UAAU,GAAkB,UAAU,CAAC;oBAC3C,IAAI,UAAU,CAAC,IAAI,KAAK,sBAAc,CAAC,aAAa,EAAE,CAAC;wBACrD,MAAM,YAAY,GAAG,UAAU,CAAC,UAAU,CAAC,IAAI,CAC7C,CAAC,CAAC,EAAE,CACF,CAAC,CAAC,IAAI,KAAK,sBAAc,CAAC,QAAQ;4BAClC,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU;4BACxC,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAC3B,CAAC;wBACF,IAAI,YAAY,IAAI,YAAY,CAAC,IAAI,KAAK,sBAAc,CAAC,QAAQ,EAAE,CAAC;4BAClE,UAAU,GAAG,YAAY,CAAC;wBAC5B,CAAC;oBACH,CAAC;oBAED,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,UAAU;wBAChB,SAAS,EAAE,uBAAuB;wBAClC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE;wBAC7B,OAAO,EAAE,WAAW;qBACrB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,OAAO;YACL,mBAAmB,CAAC,IAAkC;gBACpD,IAAI,IAAA,4BAAgB,EAAC,IAAI,CAAC,EAAE,CAAC;oBAC3B,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC;YAED,uBAAuB,CAAC,IAAsC;gBAC5D,IAAI,IAAA,4BAAgB,EAAC,IAAI,CAAC,EAAE,CAAC;oBAC3B,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["import { AST_NODE_TYPES, ESLintUtils, TSESTree } from \"@typescript-eslint/utils\";\nimport {\n hasExistingBodyInitializations,\n isParameterExplicitlyDestructured,\n isParameterInitialized,\n isParameterOnlyUsedInJSX,\n isParameterUsedInFunction,\n isReactComponent,\n} from \"../../utils/ast-utils\";\nimport { getOptionalPropsFromType } from \"../../utils/typescript-utils\";\nimport { generateSuggestions, type MessageIds } from \"./suggestion-utils\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}.ts`\n);\n\ntype Options = [\n {\n allowNullableObject?: boolean;\n allowNullableBoolean?: boolean;\n allowNullableString?: boolean;\n allowNullableNumber?: boolean;\n allowNullableEnum?: boolean;\n allowNullableStringLiteralUnion?: boolean;\n onlyRequireUsedProps?: boolean;\n },\n];\n\nexport const requireOptionalPropInitialization = createRule<Options, MessageIds>({\n name: \"require-optional-prop-initialization\",\n meta: {\n type: \"suggestion\",\n docs: {\n description: \"Require optional component props to be initialized inside the component\",\n },\n hasSuggestions: true,\n schema: [\n {\n type: \"object\",\n properties: {\n allowNullableObject: { type: \"boolean\" },\n allowNullableBoolean: { type: \"boolean\" },\n allowNullableString: { type: \"boolean\" },\n allowNullableNumber: { type: \"boolean\" },\n allowNullableEnum: { type: \"boolean\" },\n allowNullableStringLiteralUnion: { type: \"boolean\" },\n onlyRequireUsedProps: { type: \"boolean\" },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n requireInitialization: \"Optional prop '{{propName}}' should be initialized\",\n initializeProp: \"{{description}}\",\n },\n },\n defaultOptions: [\n {\n allowNullableObject: true,\n allowNullableBoolean: false,\n allowNullableString: true,\n allowNullableNumber: true,\n allowNullableEnum: false,\n allowNullableStringLiteralUnion: false,\n onlyRequireUsedProps: true,\n },\n ],\n create(context, options) {\n const config = options[0];\n\n // Helper function to check component props\n const checkComponentProps = (\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n propsParam: TSESTree.Parameter | undefined\n ) => {\n if (!propsParam) {\n return;\n }\n\n let typeAnnotation: TSESTree.TypeNode | undefined;\n\n // Handle both regular parameters (props: Props) and destructured parameters ({prop1, prop2}: Props)\n if (propsParam.type === AST_NODE_TYPES.Identifier || propsParam.type === AST_NODE_TYPES.ObjectPattern) {\n typeAnnotation = propsParam.typeAnnotation?.typeAnnotation;\n } else {\n return;\n }\n\n const optionalProps = getOptionalPropsFromType(context, typeAnnotation);\n\n if (optionalProps.length === 0) {\n return;\n }\n\n const functionBody = functionNode.body.type === AST_NODE_TYPES.BlockStatement ? functionNode.body.body : [];\n\n optionalProps.forEach(prop => {\n // Check if this prop type is allowed to be nullable based on configuration\n const isAllowed =\n (prop.type === \"object\" && config.allowNullableObject === true) ||\n (prop.type === \"boolean\" && config.allowNullableBoolean === true) ||\n (prop.type === \"string\" && config.allowNullableString === true) ||\n (prop.type === \"number\" && config.allowNullableNumber === true) ||\n (prop.type === \"enum\" && config.allowNullableEnum === true) ||\n (prop.type === \"stringLiteral\" && config.allowNullableStringLiteralUnion === true) ||\n prop.type === \"unknown\"; // Always allow unknown types\n\n if (isAllowed) {\n return;\n }\n\n // If onlyRequireUsedProps is enabled, skip unused props\n if (config.onlyRequireUsedProps === true && !isParameterUsedInFunction(context, functionNode, prop.name)) {\n return;\n }\n\n // Skip props that are not explicitly destructured (i.e., captured in rest parameters like ...restOptions)\n // and are not used in the component body - these are just being passed through\n if (\n !isParameterExplicitlyDestructured(propsParam, prop.name) &&\n !isParameterUsedInFunction(context, functionNode, prop.name)\n ) {\n return;\n }\n\n // Skip props that are only used for pass-through to child components (e.g., <Tag color={tagColor} />)\n if (isParameterOnlyUsedInJSX(context, functionNode, prop.name) === true) {\n return;\n }\n\n // Check if the prop is initialized in the function body or parameter defaults\n if (!isParameterInitialized(functionBody, prop.name, propsParam)) {\n const isDestructuredParam = propsParam.type === AST_NODE_TYPES.ObjectPattern;\n const hasBodyInits = hasExistingBodyInitializations(functionBody);\n const propsParamName = propsParam.type === AST_NODE_TYPES.Identifier ? propsParam.name : \"props\";\n\n const suggestions = generateSuggestions(\n prop,\n propsParamName,\n functionNode,\n isDestructuredParam,\n hasBodyInits,\n propsParam,\n context\n );\n\n // Find the specific property node for more precise reporting\n let reportNode: TSESTree.Node = propsParam;\n if (propsParam.type === AST_NODE_TYPES.ObjectPattern) {\n const propProperty = propsParam.properties.find(\n p =>\n p.type === AST_NODE_TYPES.Property &&\n p.key.type === AST_NODE_TYPES.Identifier &&\n p.key.name === prop.name\n );\n if (propProperty && propProperty.type === AST_NODE_TYPES.Property) {\n reportNode = propProperty;\n }\n }\n\n context.report({\n node: reportNode,\n messageId: \"requireInitialization\",\n data: { propName: prop.name },\n suggest: suggestions,\n });\n }\n });\n };\n\n return {\n FunctionDeclaration(node: TSESTree.FunctionDeclaration) {\n if (isReactComponent(node)) {\n checkComponentProps(node, node.params[0]);\n }\n },\n\n ArrowFunctionExpression(node: TSESTree.ArrowFunctionExpression) {\n if (isReactComponent(node)) {\n checkComponentProps(node, node.params[0]);\n }\n },\n };\n },\n});\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggestion-utils.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/require-optional-prop-initialization/suggestion-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { AST_NODE_TYPES, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\nimport { isParameterExplicitlyDestructured } from \"../../utils/ast-utils\";\nimport { OptionalProp } from \"../../utils/typescript-utils\";\n\nexport type MessageIds = \"requireInitialization\" | \"initializeProp\";\n\nexport type SuggestionResult = {\n messageId: MessageIds;\n data?: Record<string, unknown>;\n fix: (fixer: TSESLint.RuleFixer) => TSESLint.RuleFix | Array<TSESLint.RuleFix> | null;\n};\n\n/**\n * Helper to find and replace a property in destructuring pattern\n */\nconst createParameterInitializationFix = (propName: string, value: string, propsParam: TSESTree.Parameter) => {\n return (fixer: TSESLint.RuleFixer) => {\n if (propsParam.type === AST_NODE_TYPES.ObjectPattern) {\n const property = propsParam.properties.find(\n p => p.type === AST_NODE_TYPES.Property && p.key.type === AST_NODE_TYPES.Identifier && p.key.name === propName\n );\n if (property && property.type === AST_NODE_TYPES.Property) {\n return fixer.replaceText(property, `${propName} = ${value}`);\n }\n }\n return null;\n };\n};\n\n/**\n * Helper to create body initialization fix\n */\nconst createBodyInitializationFix = (\n propName: string,\n value: string,\n propsParamName: string,\n functionBodyStart: number\n) => {\n return (fixer: TSESLint.RuleFixer) => {\n const destructuringFix = `\\n const { ${propName} = ${value} } = ${propsParamName};`;\n return fixer.insertTextAfterRange([functionBodyStart, functionBodyStart + 1], destructuringFix);\n };\n};\n\n/**\n * Helper to create a suggestion for a specific value\n */\nconst createSuggestion = (\n propName: string,\n value: string,\n displayValue: string,\n shouldUseParameterInit: boolean,\n propsParam: TSESTree.Parameter,\n propsParamName: string,\n functionBodyStart: number\n): SuggestionResult => {\n let locationSuffix = \"\";\n let fixFunction: (fixer: TSESLint.RuleFixer) => TSESLint.RuleFix | Array<TSESLint.RuleFix> | null;\n\n if (shouldUseParameterInit) {\n locationSuffix = \" in parameter\";\n fixFunction = createParameterInitializationFix(propName, value, propsParam);\n } else {\n fixFunction = createBodyInitializationFix(propName, value, propsParamName, functionBodyStart);\n }\n\n return {\n messageId: \"initializeProp\",\n data: { description: `Initialize '${propName}' to → ${displayValue}${locationSuffix}` },\n fix: fixFunction,\n };\n};\n\n/**\n * Helper to create suggestions for a set of values\n */\nconst createSuggestionsForValues = (\n propName: string,\n values: Array<{ value: string; display: string }>,\n shouldUseParameterInit: boolean,\n propsParam: TSESTree.Parameter,\n propsParamName: string,\n functionBodyStart: number\n): Array<SuggestionResult> => {\n return values.map(({ value, display }) =>\n createSuggestion(propName, value, display, shouldUseParameterInit, propsParam, propsParamName, functionBodyStart)\n );\n};\n\n/**\n * Helper function to generate suggestions for prop initialization\n */\nexport const generateSuggestions = (\n prop: OptionalProp,\n propsParamName: string,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n isDestructuredParam: boolean,\n hasBodyInits: boolean,\n propsParam: TSESTree.Parameter,\n _context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): Array<SuggestionResult> => {\n const suggestions: Array<SuggestionResult> = [];\n\n if (functionNode.body.type !== AST_NODE_TYPES.BlockStatement) {\n return suggestions; // Can't suggest for arrow functions without block body\n }\n\n // Don't offer suggestions for props captured in rest parameters (e.g., ...rest)\n // The developer should manually handle extracting these from the rest object\n if (!isParameterExplicitlyDestructured(propsParam, prop.name)) {\n return suggestions;\n }\n\n const functionBodyStart = functionNode.body.range[0];\n const MAX_SUGGESTIONS = 5; // Don't overwhelm with too many suggestions\n\n // Decide where to place the initialization:\n // Since we know the prop is explicitly destructured (early return above handles rest params),\n // we can choose between parameter initialization or body initialization\n const isAlreadyInParameterDestructuring =\n isDestructuredParam &&\n propsParam.type === AST_NODE_TYPES.ObjectPattern &&\n propsParam.properties.some(\n p => p.type === AST_NODE_TYPES.Property && p.key.type === AST_NODE_TYPES.Identifier && p.key.name === prop.name\n );\n\n const shouldUseParameterInit = isAlreadyInParameterDestructuring || (isDestructuredParam && !hasBodyInits);\n\n // Boolean suggestions: true, false, and undefined\n if (prop.type === \"boolean\") {\n const booleanValues = [\n { value: \"true\", display: \"true\" },\n { value: \"false\", display: \"false\" },\n { value: \"undefined\", display: \"undefined\" },\n ];\n suggestions.push(\n ...createSuggestionsForValues(\n prop.name,\n booleanValues,\n shouldUseParameterInit,\n propsParam,\n propsParamName,\n functionBodyStart\n )\n );\n }\n\n // String literal suggestions: each individual literal (if not too many)\n if (prop.type === \"stringLiteral\" && prop.stringLiterals.length <= MAX_SUGGESTIONS) {\n const stringLiteralValues = [\n ...prop.stringLiterals.map(literal => ({ value: `\"${literal}\"`, display: `\"${literal}\"` })),\n { value: \"undefined\", display: \"undefined\" },\n ];\n suggestions.push(\n ...createSuggestionsForValues(\n prop.name,\n stringLiteralValues,\n shouldUseParameterInit,\n propsParam,\n propsParamName,\n functionBodyStart\n )\n );\n }\n\n // Enum suggestions: each individual enum value (if not too many)\n if (prop.type === \"enum\" && prop.enumValues.length <= MAX_SUGGESTIONS) {\n const enumValues = [\n ...prop.enumValues.map(enumValue => {\n const valueStr = typeof enumValue === \"string\" ? `\"${enumValue}\"` : String(enumValue);\n return { value: valueStr, display: valueStr };\n }),\n { value: \"undefined\", display: \"undefined\" },\n ];\n suggestions.push(\n ...createSuggestionsForValues(\n prop.name,\n enumValues,\n shouldUseParameterInit,\n propsParam,\n propsParamName,\n functionBodyStart\n )\n );\n }\n\n // String type suggestions\n if (prop.type === \"string\") {\n const stringValues = [\n { value: '\"\"', display: '\"\"' },\n { value: \"undefined\", display: \"undefined\" },\n ];\n suggestions.push(\n ...createSuggestionsForValues(\n prop.name,\n stringValues,\n shouldUseParameterInit,\n propsParam,\n propsParamName,\n functionBodyStart\n )\n );\n }\n\n // Number type suggestions\n if (prop.type === \"number\") {\n const numberValues = [\n { value: \"0\", display: \"0\" },\n { value: \"undefined\", display: \"undefined\" },\n ];\n suggestions.push(\n ...createSuggestionsForValues(\n prop.name,\n numberValues,\n shouldUseParameterInit,\n propsParam,\n propsParamName,\n functionBodyStart\n )\n );\n }\n\n // Object/unknown type suggestions\n if (prop.type === \"object\" || prop.type === \"unknown\") {\n const typeDisplay = prop.type === \"unknown\" ? \"any value\" : prop.type;\n suggestions.push(\n createSuggestion(\n prop.name,\n \"undefined\",\n `undefined (${typeDisplay})`,\n shouldUseParameterInit,\n propsParam,\n propsParamName,\n functionBodyStart\n )\n );\n }\n\n return suggestions;\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-storybook-folder-landing-page.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/require-storybook-folder-landing-page/require-storybook-folder-landing-page.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Require a Storybook landing page (`*.docs.mdx` with `<Meta title=\"...\">`) for every ancestor\n * FOLDER implied by a story's title.\n *\n * Architecture: per-story-file rule. Each `*.stories.@(js|jsx|ts|tsx)` file declares a Storybook\n * `title` (e.g. \"Hooks/react-core-hooks/useDebounce\"). The folders implied by that title are the\n * accumulated path prefixes EXCLUDING the story leaf (here: \"Hooks\" and \"Hooks/react-core-hooks\").\n * Every such folder must have a landing page: a `*.docs.mdx` somewhere in the workspace whose\n * `<Meta title=\"FOLDER\" />` EXACTLY equals the folder path, with non-empty body and no TODO marker.\n *\n * The rule is REPORT-ONLY: it does not scaffold files. Creating a separate `*.docs.mdx` cannot be\n * expressed as a pure ESLint fix, and ESLint evaluates fix/suggestion callbacks on every lint pass\n * (not only under `--fix`), so a file-writing fix would write stubs during ordinary editor/CI lint.\n * Stub scaffolding is therefore delivered as a separate, explicit command (tracked as a follow-up).\n *\n * See README.md for incorrect/correct examples.\n */\n\nimport { AST_NODE_TYPES, ESLintUtils, TSESTree } from \"@typescript-eslint/utils\";\nimport * as crypto from \"crypto\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { findNearestFile } from \"../../utils/file-utils\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name =>\n `https://github.com/trackunit/manager/blob/master/libs/eslint/plugin-trackunit/src/lib/rules/${name}/${name}.ts`\n);\n\ntype MessageIds = \"missingLandingPage\";\ntype Options = [];\n\n/** Canonical TODO marker. A landing page still containing this marker does NOT satisfy the rule. */\nexport const STORYBOOK_LANDING_PAGE_TODO_MARKER = \"{/* TODO: storybook-folder-landing-page */}\";\n\n/**\n * Canonical permalink to the how-to-author doc. Single source of truth, embedded in the rule's\n * error message so developers tripping the rule get a direct link. The `master` permalink stays\n * stable across file moves within the (internal) repo.\n */\nexport const STORYBOOK_LANDING_PAGE_DOCS_URL =\n \"https://github.com/Trackunit/manager/blob/master/docs/STORYBOOK-LANDING-PAGES.md\";\n\n/** A discovered `*.docs.mdx` landing page keyed by its exact `<Meta title>`. */\ntype LandingPageEntry = {\n filePath: string;\n body: string;\n};\n\ntype LandingPageScan = {\n fingerprint: string;\n landingPages: Map<string, LandingPageEntry>;\n};\n\n/**\n * Cache of landing-page scans, keyed by workspace root. The cached value is reused only while the\n * current docs-file fingerprint matches, so long-lived ESLint processes pick up newly added or\n * edited landing pages without requiring an ESLint server restart.\n */\nconst landingPageCache = new Map<string, LandingPageScan>();\n\n/** Clear the module-level scan cache (primarily for tests). */\nexport const clearLandingPageCache = (): void => {\n landingPageCache.clear();\n};\n\nconst SKIP_DIRECTORIES = new Set([\"node_modules\", \"dist\", \".git\", \".nx\"]);\n\n// Match `title=\"...\"` anywhere within an opening `<Meta ...>` tag (attribute order independent).\nconst META_TITLE_REGEX = /<Meta\\b[^>]*?\\btitle\\s*=\\s*(\"|')(.*?)\\1/;\n\nconst STORY_FILE_REGEX = /\\.stories\\.(js|jsx|ts|tsx)$/;\nconst DOCS_MDX_REGEX = /\\.docs\\.mdx$/;\n\n/** Recursively collect absolute paths of every `*.docs.mdx` file under `dir`. */\nconst collectDocsMdxFiles = (dir: string): Array<string> => {\n const result: Array<string> = [];\n let entries: Array<fs.Dirent>;\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return result;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (!SKIP_DIRECTORIES.has(entry.name)) {\n result.push(...collectDocsMdxFiles(fullPath));\n }\n } else if (DOCS_MDX_REGEX.test(entry.name)) {\n result.push(fullPath);\n }\n }\n\n return result;\n};\n\n/** Strip import lines and the `<Meta .../>` tag, leaving the documentation body. */\nconst extractBody = (contents: string): string => {\n return contents\n .split(\"\\n\")\n .filter(line => !/^\\s*import\\s/.test(line))\n .join(\"\\n\")\n .replace(/<Meta\\b[^>]*\\/>/, \"\")\n .trim();\n};\n\n/** Scan the workspace for `*.docs.mdx` landing pages, building a title -> entry map. */\nconst scanLandingPages = (workspaceRoot: string): LandingPageScan => {\n const landingPages = new Map<string, LandingPageEntry>();\n const hash = crypto.createHash(\"sha256\");\n\n for (const filePath of collectDocsMdxFiles(workspaceRoot).toSorted()) {\n hash.update(filePath);\n hash.update(\"\\0\");\n\n let contents: string;\n try {\n contents = fs.readFileSync(filePath, \"utf-8\");\n } catch {\n hash.update(\"unreadable\");\n hash.update(\"\\0\");\n continue;\n }\n\n hash.update(contents);\n hash.update(\"\\0\");\n\n const match = META_TITLE_REGEX.exec(contents);\n if (match && typeof match[2] === \"string\") {\n landingPages.set(match[2], { filePath, body: extractBody(contents) });\n }\n }\n\n return { fingerprint: hash.digest(\"hex\"), landingPages };\n};\n\n/** Get landing pages from cache when the current docs-file fingerprint is unchanged. */\nconst getLandingPages = (workspaceRoot: string): Map<string, LandingPageEntry> => {\n const scan = scanLandingPages(workspaceRoot);\n const cached = landingPageCache.get(workspaceRoot);\n if (cached?.fingerprint === scan.fingerprint) {\n return cached.landingPages;\n }\n\n landingPageCache.set(workspaceRoot, scan);\n return scan.landingPages;\n};\n\n/** Derive ancestor folder paths from a title, dropping the story leaf. */\nconst deriveFolders = (title: string): Array<string> => {\n const segments = title.split(\"/\");\n const folders: Array<string> = [];\n // Drop the last segment (story leaf); accumulate prefixes for the rest.\n for (let i = 1; i < segments.length; i++) {\n folders.push(segments.slice(0, i).join(\"/\"));\n }\n return folders;\n};\n\n/** A folder is satisfied by a landing page entry with non-empty body and no TODO marker. */\nconst isSatisfied = (entry: LandingPageEntry | undefined): boolean => {\n if (!entry) {\n return false;\n }\n if (entry.body.length === 0) {\n return false;\n }\n return !entry.body.includes(STORYBOOK_LANDING_PAGE_TODO_MARKER);\n};\n\n/** Unwrap satisfies/as wrappers around an expression. */\nconst unwrapExpression = (node: TSESTree.Expression): TSESTree.Expression => {\n let current = node;\n while (current.type === AST_NODE_TYPES.TSSatisfiesExpression || current.type === AST_NODE_TYPES.TSAsExpression) {\n current = current.expression;\n }\n return current;\n};\n\n/** Extract a string-literal `title` property from an object expression, if present. */\nconst getTitleFromObject = (object: TSESTree.ObjectExpression): TSESTree.Literal | null => {\n for (const property of object.properties) {\n if (\n property.type === AST_NODE_TYPES.Property &&\n property.key.type === AST_NODE_TYPES.Identifier &&\n property.key.name === \"title\" &&\n property.value.type === AST_NODE_TYPES.Literal &&\n typeof property.value.value === \"string\"\n ) {\n return property.value;\n }\n }\n return null;\n};\n\nexport const requireStorybookFolderLandingPage = createRule<Options, MessageIds>({\n name: \"require-storybook-folder-landing-page\",\n meta: {\n type: \"problem\",\n docs: {\n description: \"Require a Storybook landing page (*.docs.mdx) for every ancestor folder implied by a story's title\",\n },\n schema: [],\n messages: {\n // URL embedded from the single-source-of-truth const (see STORYBOOK_LANDING_PAGE_DOCS_URL).\n missingLandingPage: `[require-storybook-folder-landing-page] Missing Storybook landing page for folder \"{{folder}}\". The <Meta title> must equal \"{{folder}}\" exactly (no extra leaf). Add a *.docs.mdx with <Meta title=\"{{folder}}\" /> and real content. See ${STORYBOOK_LANDING_PAGE_DOCS_URL} for how to author one.`,\n },\n },\n defaultOptions: [],\n create(context) {\n const currentFile = context.filename;\n\n // Only analyze story files (never .docs.* or .mdx).\n if (!STORY_FILE_REGEX.test(currentFile)) {\n return {};\n }\n\n const nxJsonPath = findNearestFile(currentFile, \"nx.json\");\n if (nxJsonPath === null) {\n return {};\n }\n const workspaceRoot = path.dirname(nxJsonPath);\n\n const reportForObject = (titleNode: TSESTree.Literal, reportNode: TSESTree.Node): void => {\n const title = titleNode.value;\n if (typeof title !== \"string\") {\n return;\n }\n\n const folders = deriveFolders(title);\n if (folders.length === 0) {\n return;\n }\n\n const landingPages = getLandingPages(workspaceRoot);\n\n for (const folder of folders) {\n const entry = landingPages.get(folder);\n if (isSatisfied(entry)) {\n continue;\n }\n\n context.report({\n node: reportNode,\n messageId: \"missingLandingPage\",\n data: { folder },\n });\n }\n };\n\n return {\n ExportDefaultDeclaration(node: TSESTree.ExportDefaultDeclaration) {\n const declaration = node.declaration;\n\n // Shape 1: export default { title: \"...\" }\n if (declaration.type === AST_NODE_TYPES.ObjectExpression) {\n const titleNode = getTitleFromObject(declaration);\n if (titleNode) {\n reportForObject(titleNode, node);\n }\n return;\n }\n\n // Shape 2: const meta = { title: \"...\" } satisfies Meta; export default meta;\n if (declaration.type === AST_NODE_TYPES.Identifier) {\n const variable = context.sourceCode\n .getScope(node)\n .references.find(ref => ref.identifier === declaration)?.resolved;\n const definition = variable?.defs[0];\n if (definition && definition.node.type === AST_NODE_TYPES.VariableDeclarator && definition.node.init) {\n const initializer = unwrapExpression(definition.node.init);\n if (initializer.type === AST_NODE_TYPES.ObjectExpression) {\n const titleNode = getTitleFromObject(initializer);\n if (titleNode) {\n reportForObject(titleNode, node);\n }\n }\n }\n }\n },\n };\n },\n});\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules-map.js","sourceRoot":"","sources":["../../../../../../libs/eslint/plugin-trackunit/src/lib/rules-map.ts"],"names":[],"mappings":";;;AACA,6HAAuH;AACvH,6HAAqH;AACrH,qJAA6I;AAC7I,oHAA8G;AAC9G,8GAAwG;AACxG,wGAAkG;AAClG,6KAAmK;AACnK,qJAA4I;AAC5I,+IAAmI;AACnI,qGAAgG;AAChG,2GAAqG;AACrG,kGAA4F;AAC5F,iHAA4G;AAC5G,+IAAwI;AACxI,qGAAgG;AAChG,2JAAkJ;AAClJ,0HAAqH;AACrH,gIAA0H;AAC1H,kJAA2I;AAC3I,4IAAsI;AACtI,+IAAwI;AAE3H,QAAA,QAAQ,GAAG;IACtB,iCAAiC,EAAE,8DAA4B;IAC/D,wBAAwB,EAAE,4CAAmB;IAC7C,iCAAiC,EAAE,4DAA0B;IAC7D,0BAA0B,EAAE,gDAAqB;IACjD,yBAAyB,EAAE,+CAAqB;IAChD,8BAA8B,EAAE,wDAAyB;IACzD,4BAA4B,EAAE,oDAAuB;IACrD,iDAAiD,EAAE,0FAAwC;IAC3F,yCAAyC,EAAE,4EAAkC;IAC7E,uCAAuC,EAAE,oEAA4B;IACrE,2BAA2B,EAAE,kDAAsB;IACnD,gCAAgC,EAAE,6DAA4B;IAC9D,yCAAyC,EAAE,2EAAiC;IAC5E,6BAA6B,EAAE,uDAAyB;IACxD,2CAA2C,EAAE,+EAAmC;IAChF,uCAAuC,EAAE,yEAAiC;IAC1E,sCAAsC,EAAE,wEAAiC;IACzE,kCAAkC,EAAE,gEAA6B;IACjE,yBAAyB,EAAE,+CAAqB;IAChD,wCAAwC,EAAE,2EAAkC;IAC5E,uCAAuC,EAAE,yEAAiC;CACM,CAAC","sourcesContent":["import { ESLintUtils } from \"@typescript-eslint/utils\";\nimport { componentNameMatchesFilename } from \"./rules/component-name-matches-filename/component-name-matches-filename\";\nimport { cvaMergeBaseClassesAsArray } from \"./rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array\";\nimport { designGuidelineButtonIconSizeMatch } from \"./rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match\";\nimport { noDeprecatedGraphqlFields } from \"./rules/no-deprecated-graphql-fields/no-deprecated-graphql-fields\";\nimport { noDynamicTranslationKey } from \"./rules/no-dynamic-translation-key/no-dynamic-translation-key\";\nimport { noInternalBarrelFiles } from \"./rules/no-internal-barrel-files/no-internal-barrel-files\";\nimport { noInternalGraphqlWhenTaggedWithGqlPublic } from \"./rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public\";\nimport { noJestMockTrackunitReactCoreHooks } from \"./rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks\";\nimport { noTemplateStringsInClassName } from \"./rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop\";\nimport { noTypescriptAssertion } from \"./rules/no-typescript-assertion/no-typescript-assertion\";\nimport { noUnusedTranslationKey } from \"./rules/no-unused-translation-key/no-unused-translation-key\";\nimport { oneComponentPerFile } from \"./rules/one-component-per-file/one-component-per-file\";\nimport { preferDestructuredImports } from \"./rules/prefer-destructured-imports/prefer-destructured-imports\";\nimport { preferEventSpecificCallbackNaming } from \"./rules/prefer-event-specific-callback-naming/prefer-event-specific-callback-naming\";\nimport { preferFieldComponents } from \"./rules/prefer-field-components/prefer-field-components\";\nimport { preferMouseEventHandlerInReactProps } from \"./rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props\";\nimport { requireClassnameAlternatives } from \"./rules/require-classname-alternatives/require-classname-alternatives\";\nimport { requireComponentPropContracts } from \"./rules/require-component-prop-contracts/require-component-prop-contracts\";\nimport { requireListItemVirtualizationProps } from \"./rules/require-list-item-virtualization-props/require-list-item-virtualization-props\";\nimport { requireOptionalPropInitialization } from \"./rules/require-optional-prop-initialization/require-optional-prop-initialization\";\nimport { requireStorybookFolderLandingPage } from \"./rules/require-storybook-folder-landing-page/require-storybook-folder-landing-page\";\n\nexport const rulesMap = {\n \"component-name-matches-filename\": componentNameMatchesFilename,\n \"one-component-per-file\": oneComponentPerFile,\n \"cva-merge-base-classes-as-array\": cvaMergeBaseClassesAsArray,\n \"no-internal-barrel-files\": noInternalBarrelFiles,\n \"no-typescript-assertion\": noTypescriptAssertion,\n \"no-deprecated-graphql-fields\": noDeprecatedGraphqlFields,\n \"no-dynamic-translation-key\": noDynamicTranslationKey,\n \"no-internal-graphql-when-tagged-with-gql-public\": noInternalGraphqlWhenTaggedWithGqlPublic,\n \"design-guideline-button-icon-size-match\": designGuidelineButtonIconSizeMatch,\n \"no-template-strings-in-classname-prop\": noTemplateStringsInClassName,\n \"no-unused-translation-key\": noUnusedTranslationKey,\n \"require-classname-alternatives\": requireClassnameAlternatives,\n \"no-jest-mock-trackunit-react-core-hooks\": noJestMockTrackunitReactCoreHooks,\n \"prefer-destructured-imports\": preferDestructuredImports,\n \"prefer-mouse-event-handler-in-react-props\": preferMouseEventHandlerInReactProps,\n \"prefer-event-specific-callback-naming\": preferEventSpecificCallbackNaming,\n \"require-optional-prop-initialization\": requireOptionalPropInitialization,\n \"require-component-prop-contracts\": requireComponentPropContracts,\n \"prefer-field-components\": preferFieldComponents,\n \"require-list-item-virtualization-props\": requireListItemVirtualizationProps,\n \"require-storybook-folder-landing-page\": requireStorybookFolderLandingPage,\n} satisfies Record<string, ESLintUtils.RuleModule<string, ReadonlyArray<unknown>>>;\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/ast-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { ASTUtils, AST_NODE_TYPES, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\n\n/**\n * Utility functions for analyzing AST nodes and function structure in ESLint rules.\n *\n * ## Core Utilities\n * - `isInParameterList()` - Check if a node is in a function's parameter list\n *\n * ## Parameter Analysis (Parameter → Usage)\n * - `isParameterExplicitlyDestructured()` - Check if parameter is explicitly destructured\n * - `isParameterInitialized()` - Check if parameter has a default value\n * - `isParameterUsedInFunction()` - Check if parameter is used in function body\n * - `hasExistingBodyInitializations()` - Check for initialization patterns in function body\n *\n * ## Identifier Origin Analysis (Usage → Origin)\n * - `getIdentifierParameterOrigin()` - Trace identifier back to see if it's from a parameter (rich return)\n * - `isIdentifierFromParameter()` - Boolean helper to check if identifier is from a parameter\n * - `isIdentifierFromRenderPropCallback()` - Check if identifier is from a render prop callback parameter\n *\n * ## JSX/React Specific\n * - `isReactComponent()` - Check if function is likely a React component\n * - `functionReturnsJSX()` - Check if function body returns JSX\n * - `functionReturnsIntrinsicJSX()` - Check if function body returns intrinsic JSX tags (e.g. `div`, `span`)\n * - `isParameterOnlyUsedInJSX()` - Check if parameter is only used in JSX attributes\n */\n\n/**\n * Helper function to check if a node is in the parameter list\n */\nconst isInParameterList = (\n node: TSESTree.Node,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression\n): boolean => {\n let current = node.parent;\n while (current) {\n // Check if current node is one of the function parameters\n const isParam = functionNode.params.some(param => param === current);\n if (isParam) {\n return true;\n }\n current = current.parent;\n }\n return false;\n};\n\n/**\n * Check if a parameter is explicitly destructured in the parameter list\n * (vs. captured in rest parameters like ...restOptions)\n */\nexport const isParameterExplicitlyDestructured = (parameter: TSESTree.Parameter, paramName: string): boolean => {\n if (parameter.type !== AST_NODE_TYPES.ObjectPattern) {\n return false;\n }\n\n // Check if the parameter is explicitly listed in the destructuring\n return parameter.properties.some(property => {\n if (property.type === AST_NODE_TYPES.Property && property.key.type === AST_NODE_TYPES.Identifier) {\n return property.key.name === paramName;\n }\n return false;\n });\n};\n\n/**\n * Check if there are any existing parameter initializations in the function body\n */\nexport const hasExistingBodyInitializations = (functionBody: Array<TSESTree.Statement>): boolean => {\n for (const stmt of functionBody) {\n // Check for destructuring with defaults: const { param = defaultValue } = params\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.ObjectPattern &&\n stmt.declarations[0].id.properties.some(\n prop => prop.type === AST_NODE_TYPES.Property && prop.value.type === AST_NODE_TYPES.AssignmentPattern\n )\n ) {\n return true;\n }\n\n // Check for variable declarations with defaults: const param = params.param ?? defaultValue\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].init?.type === AST_NODE_TYPES.LogicalExpression &&\n (stmt.declarations[0].init.operator === \"??\" || stmt.declarations[0].init.operator === \"||\")\n ) {\n return true;\n }\n }\n return false;\n};\n\n/**\n * Check if a parameter is initialized in the function body or parameter defaults\n */\nexport const isParameterInitialized = (\n functionBody: Array<TSESTree.Statement>,\n paramName: string,\n parameter?: TSESTree.Parameter\n): boolean => {\n // First check if the parameter has a default value in the parameter destructuring\n if (parameter && parameter.type === AST_NODE_TYPES.ObjectPattern) {\n for (const property of parameter.properties) {\n if (property.type === AST_NODE_TYPES.Property && property.value.type === AST_NODE_TYPES.AssignmentPattern) {\n // Handle both identifier keys (paramName) and string literal keys (\"param-name\")\n const keyName =\n property.key.type === AST_NODE_TYPES.Identifier\n ? property.key.name\n : property.key.type === AST_NODE_TYPES.Literal && typeof property.key.value === \"string\"\n ? property.key.value\n : null;\n\n if (keyName === paramName) {\n return true; // Found default value in parameter: {paramName = defaultValue}\n }\n }\n }\n }\n\n // Then check for initialization patterns in the function body\n for (const stmt of functionBody) {\n // Check for destructuring with defaults: const { param = defaultValue } = params\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.ObjectPattern\n ) {\n const pattern = stmt.declarations[0].id;\n for (const property of pattern.properties) {\n if (\n property.type === AST_NODE_TYPES.Property &&\n property.key.type === AST_NODE_TYPES.Identifier &&\n property.key.name === paramName &&\n property.value.type === AST_NODE_TYPES.AssignmentPattern\n ) {\n return true;\n }\n }\n }\n\n // Check for variable declarations with defaults: const param = params.param ?? defaultValue\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.Identifier &&\n stmt.declarations[0].id.name === paramName &&\n stmt.declarations[0].init?.type === AST_NODE_TYPES.LogicalExpression &&\n (stmt.declarations[0].init.operator === \"??\" || stmt.declarations[0].init.operator === \"||\")\n ) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * Check if a parameter is used within the function body\n */\nexport const isParameterUsedInFunction = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): boolean => {\n // Use TypeScript-ESLint's built-in findVariable utility for more robust variable detection\n const scope = context.sourceCode.getScope(functionNode);\n const variable = ASTUtils.findVariable(scope, paramName);\n\n if (variable) {\n // Check if the variable has any references (excluding the parameter definition)\n const references = variable.references.filter(ref => {\n // Exclude the parameter declaration itself\n const refNode = ref.identifier;\n return !isInParameterList(refNode, functionNode);\n });\n\n // Additional check: if the variable is only referenced in object literal shorthand property names\n // (like { placement: result.placement }), it's not actually using the parameter variable\n const actualUsageReferences = references.filter(ref => {\n const parent = ref.identifier.parent;\n\n // Skip if this is just a property key in an object literal\n // Example: { placement: result.placement } - the first 'placement' is just a key, not usage\n if (\n parent.type === AST_NODE_TYPES.Property &&\n parent.key === ref.identifier &&\n parent.value !== ref.identifier &&\n !parent.shorthand\n ) {\n return false;\n }\n\n return true;\n });\n\n if (actualUsageReferences.length > 0) {\n return true;\n }\n }\n\n // If direct variable reference not found, check for member access on rest parameters\n // e.g., rest.paramName, params.paramName, etc.\n const restParameters: Array<{ name: string; param: TSESTree.Parameter }> = [];\n\n // Look for rest elements in both direct params and inside object patterns\n functionNode.params.forEach(param => {\n if (param.type === AST_NODE_TYPES.RestElement && param.argument.type === AST_NODE_TYPES.Identifier) {\n // Direct rest parameter: (...rest: Params)\n restParameters.push({ name: param.argument.name, param });\n } else if (param.type === AST_NODE_TYPES.ObjectPattern) {\n // Look for rest elements inside object patterns: ({ param1, ...rest }: Params)\n param.properties.forEach(property => {\n if (property.type === AST_NODE_TYPES.RestElement && property.argument.type === AST_NODE_TYPES.Identifier) {\n restParameters.push({ name: property.argument.name, param });\n }\n });\n }\n });\n\n if (restParameters.length === 0) {\n return false;\n }\n\n // Check if the function body contains rest.paramName patterns\n const functionText = context.sourceCode.getText(functionNode);\n\n for (const restParam of restParameters) {\n const pattern = new RegExp(`\\\\b${restParam.name}\\\\.${paramName}\\\\b`);\n if (pattern.test(functionText)) {\n return true;\n }\n }\n\n return false;\n};\n\ntype FunctionLikeNode = TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression;\n\nconst jsxTagNameIsIntrinsic = (name: TSESTree.JSXTagNameExpression): boolean =>\n name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/.test(name.name);\n\nconst nodeContainsJSX = (node: TSESTree.Node): boolean => {\n if (node.type === AST_NODE_TYPES.JSXElement) {\n return true;\n }\n\n if (node.type === AST_NODE_TYPES.JSXFragment) {\n return true;\n }\n\n if (node.type === AST_NODE_TYPES.ConditionalExpression) {\n return nodeContainsJSX(node.consequent) || nodeContainsJSX(node.alternate);\n }\n\n if (node.type === AST_NODE_TYPES.LogicalExpression) {\n return nodeContainsJSX(node.left) || nodeContainsJSX(node.right);\n }\n\n return false;\n};\n\nconst nodeContainsIntrinsicJSX = (node: TSESTree.Node): boolean => {\n if (node.type === AST_NODE_TYPES.JSXElement) {\n if (jsxTagNameIsIntrinsic(node.openingElement.name)) {\n return true;\n }\n\n return node.children.some(child => {\n if (child.type === AST_NODE_TYPES.JSXElement || child.type === AST_NODE_TYPES.JSXFragment) {\n return nodeContainsIntrinsicJSX(child);\n }\n\n if (\n child.type === AST_NODE_TYPES.JSXExpressionContainer &&\n child.expression.type !== AST_NODE_TYPES.JSXEmptyExpression\n ) {\n return nodeContainsIntrinsicJSX(child.expression);\n }\n\n return false;\n });\n }\n\n if (node.type === AST_NODE_TYPES.JSXFragment) {\n return node.children.some(child => {\n if (child.type === AST_NODE_TYPES.JSXElement || child.type === AST_NODE_TYPES.JSXFragment) {\n return nodeContainsIntrinsicJSX(child);\n }\n\n if (\n child.type === AST_NODE_TYPES.JSXExpressionContainer &&\n child.expression.type !== AST_NODE_TYPES.JSXEmptyExpression\n ) {\n return nodeContainsIntrinsicJSX(child.expression);\n }\n\n return false;\n });\n }\n\n if (node.type === AST_NODE_TYPES.ConditionalExpression) {\n return nodeContainsIntrinsicJSX(node.consequent) || nodeContainsIntrinsicJSX(node.alternate);\n }\n\n if (node.type === AST_NODE_TYPES.LogicalExpression) {\n return nodeContainsIntrinsicJSX(node.left) || nodeContainsIntrinsicJSX(node.right);\n }\n\n return false;\n};\n\nexport const functionReturnsJSX = (node: FunctionLikeNode): boolean => {\n if (node.body.type === AST_NODE_TYPES.BlockStatement) {\n return node.body.body.some(\n statement =>\n statement.type === AST_NODE_TYPES.ReturnStatement &&\n statement.argument !== null &&\n nodeContainsJSX(statement.argument)\n );\n }\n\n return nodeContainsJSX(node.body);\n};\n\nexport const functionReturnsIntrinsicJSX = (node: FunctionLikeNode): boolean => {\n if (node.body.type === AST_NODE_TYPES.BlockStatement) {\n return node.body.body.some(\n statement =>\n statement.type === AST_NODE_TYPES.ReturnStatement &&\n statement.argument !== null &&\n nodeContainsIntrinsicJSX(statement.argument)\n );\n }\n\n return nodeContainsIntrinsicJSX(node.body);\n};\n\n/**\n * Check if a function is likely a React component based on naming and JSX usage\n */\nexport const isReactComponent = (node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression): boolean => {\n // Check if function name starts with uppercase (React convention)\n const functionName = node.type === AST_NODE_TYPES.FunctionDeclaration ? node.id?.name : null;\n const startsWithUppercase = /^[A-Z]/;\n if (functionName && startsWithUppercase.test(functionName)) {\n return true;\n }\n\n return functionReturnsJSX(node);\n};\n\n/**\n * Check if a parameter is only used in JSX attributes (pass-through to child components)\n * and nowhere else in the function body\n */\nexport const isParameterOnlyUsedInJSX = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): boolean => {\n // Use TypeScript-ESLint's built-in findVariable utility for robust variable detection\n const scope = context.sourceCode.getScope(functionNode);\n const variable = ASTUtils.findVariable(scope, paramName);\n\n if (!variable) {\n return false;\n }\n\n // Get all references to the parameter (excluding the parameter definition)\n const references = variable.references.filter(ref => {\n const refNode = ref.identifier;\n return !isInParameterList(refNode, functionNode);\n });\n\n if (references.length === 0) {\n return false;\n }\n\n // Check if all references are only in JSX attribute expressions\n const allReferencesAreJSXAttributes = references.every(ref => {\n const identifier = ref.identifier;\n let current = identifier.parent;\n\n // Walk up the AST to find if this identifier is used in a JSX attribute\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, @typescript-eslint/strict-boolean-expressions\n while (current) {\n // Check if we're in a JSX attribute expression: <Component prop={value} />\n if (current.type === AST_NODE_TYPES.JSXExpressionContainer) {\n const jsxParent = current.parent;\n if (jsxParent.type === AST_NODE_TYPES.JSXAttribute) {\n return true;\n }\n }\n\n // Check if we're in a JSX spread attribute: <Component {...props} />\n if (current.type === AST_NODE_TYPES.JSXSpreadAttribute) {\n return true;\n }\n\n // Allow dependency arrays for React hooks (useEffect, useMemo, useCallback, etc.)\n // These are acceptable for pass-through props since they're tracking the JSX usage\n if (current.type === AST_NODE_TYPES.ArrayExpression) {\n const callParent = current.parent;\n if (\n callParent.type === AST_NODE_TYPES.CallExpression &&\n callParent.callee.type === AST_NODE_TYPES.Identifier &&\n (callParent.callee.name.startsWith(\"use\") ||\n callParent.callee.name === \"useMemo\" ||\n callParent.callee.name === \"useCallback\" ||\n callParent.callee.name === \"useEffect\")\n ) {\n return true; // Allow dependency array usage\n }\n }\n\n // Stop if we reach certain node types that indicate we're not in JSX context\n if (\n current.type === AST_NODE_TYPES.VariableDeclarator ||\n current.type === AST_NODE_TYPES.AssignmentExpression ||\n current.type === AST_NODE_TYPES.CallExpression ||\n current.type === AST_NODE_TYPES.LogicalExpression ||\n current.type === AST_NODE_TYPES.ConditionalExpression ||\n current.type === AST_NODE_TYPES.BinaryExpression\n ) {\n return false;\n }\n\n if (!current.parent) {\n break;\n }\n current = current.parent;\n }\n\n return false;\n });\n\n return allReferencesAreJSXAttributes;\n};\n\n// ============================================================\n// Identifier Origin Analysis (traces usage back to definition)\n// ============================================================\n\n/**\n * Result of tracing an identifier back to its origin.\n * Used to distinguish between different ways an identifier can come from a function parameter.\n */\nexport type ParameterOriginResult =\n | {\n isFromParameter: true;\n /**\n * How the identifier relates to the parameter:\n * - \"direct-parameter\": Direct parameter, e.g., `(onClose) => ...`\n * - \"destructured-in-signature\": Destructured in function signature, e.g., `({ onClose }) => ...`\n * - \"destructured-in-body\": Destructured in function body, e.g., `const { onClose } = props`\n */\n originType: \"direct-parameter\" | \"destructured-in-signature\" | \"destructured-in-body\";\n }\n | { isFromParameter: false };\n\n/**\n * Checks if a variable is a function parameter.\n */\nconst isVariableAParameter = (variable: { defs: ReadonlyArray<{ type: string }> }): boolean => {\n return variable.defs.some(def => def.type === \"Parameter\");\n};\n\n/**\n * Traces an identifier back to determine if it originates from a function parameter.\n * Returns detailed information about how the identifier relates to the parameter.\n *\n * This is used to distinguish between:\n * - Props passed through: `({ onClose }) => <button onClick={onClose} />` - destructured-in-signature\n * - Props destructured in body: `(props) => { const { onClose } = props; }` - destructured-in-body\n * - Direct parameter: `(onClose) => ...` - direct-parameter\n * - Internal functions: `const handleClose = () => {}; <button onClick={handleClose} />` - not from parameter\n * - Hook results: `const { mutate } = useMutation(); <button onClick={mutate} />` - not from parameter\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns ParameterOriginResult with isFromParameter and originType if applicable\n * @example\n * // Direct parameter\n * const MyComponent = (onClose) => <button onClick={onClose} />;\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"direct-parameter\" }\n * @example\n * // Destructured in signature\n * const MyComponent = ({ onClose }) => <button onClick={onClose} />;\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"destructured-in-signature\" }\n * @example\n * // Destructured in body\n * const MyComponent = (props) => {\n * const { onClose } = props;\n * return <button onClick={onClose} />;\n * };\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"destructured-in-body\" }\n * @example\n * // Not from parameter (internal function)\n * const MyComponent = () => {\n * const handleClose = () => {};\n * return <button onClick={handleClose} />;\n * };\n * // getIdentifierParameterOrigin(handleClose) => { isFromParameter: false }\n */\nconst getIdentifierParameterOrigin = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): ParameterOriginResult => {\n const scope = context.sourceCode.getScope(identifier);\n const variable = scope.references.find(ref => ref.identifier === identifier)?.resolved;\n\n if (!variable) {\n return { isFromParameter: false };\n }\n\n // Check the variable's definitions\n for (const definition of variable.defs) {\n // Check if defined as a direct function parameter\n if (definition.type === \"Parameter\") {\n // Direct parameter: (onClose) => ...\n return { isFromParameter: true, originType: \"direct-parameter\" };\n }\n\n // Check for destructured variable in body: const { onClose } = props\n // definition.type is \"Variable\" and definition.node is VariableDeclarator\n if (definition.type === \"Variable\") {\n const declarator = definition.node;\n\n // Check if the left side is an ObjectPattern (destructuring)\n if (declarator.id.type === AST_NODE_TYPES.ObjectPattern) {\n const init = declarator.init;\n\n // Check if destructured from an identifier that is a parameter\n if (init?.type === AST_NODE_TYPES.Identifier) {\n const initScope = context.sourceCode.getScope(init);\n const initVariable = initScope.references.find(ref => ref.identifier === init)?.resolved;\n\n if (initVariable && isVariableAParameter(initVariable)) {\n return { isFromParameter: true, originType: \"destructured-in-body\" };\n }\n }\n }\n }\n\n // Check if it's a destructured parameter directly in function signature\n // Pattern: ({ onClose }) => ... or ({ onClose }: Props) => ...\n if (definition.node.type === AST_NODE_TYPES.Property) {\n // Check direct parent - should be ObjectPattern for destructured props\n const objectPattern = definition.node.parent;\n if (objectPattern.type !== AST_NODE_TYPES.ObjectPattern) {\n continue;\n }\n\n // Check if this ObjectPattern is a function parameter\n const objectPatternParent = objectPattern.parent;\n\n if (\n objectPatternParent.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n objectPatternParent.type === AST_NODE_TYPES.FunctionExpression ||\n objectPatternParent.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n // Check if the ObjectPattern is in the params\n const isParam = objectPatternParent.params.includes(objectPattern);\n if (isParam) {\n return { isFromParameter: true, originType: \"destructured-in-signature\" };\n }\n }\n\n // Also check for AssignmentPattern wrapper: ({ onClose = defaultFn }) => ...\n if (objectPatternParent.type === AST_NODE_TYPES.AssignmentPattern) {\n const assignmentParent = objectPatternParent.parent;\n\n if (\n assignmentParent.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n assignmentParent.type === AST_NODE_TYPES.FunctionExpression ||\n assignmentParent.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n const isParam = assignmentParent.params.includes(objectPatternParent);\n if (isParam) {\n return { isFromParameter: true, originType: \"destructured-in-signature\" };\n }\n }\n }\n }\n }\n\n return { isFromParameter: false };\n};\n\n/**\n * Checks if an identifier originates from a function parameter.\n * This is a simplified boolean helper that wraps `getIdentifierParameterOrigin`.\n *\n * Use this when you only need to know if an identifier comes from a parameter,\n * without needing to know how it was destructured.\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns true if the identifier originates from a function parameter\n * @see getIdentifierParameterOrigin for detailed origin information\n */\nexport const isIdentifierFromParameter = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): boolean => getIdentifierParameterOrigin(identifier, context).isFromParameter;\n\n/**\n * Checks if an identifier's parameter comes from a render prop callback.\n *\n * Render prop pattern: `{callback => <Component onClick={callback} />}`\n *\n * The function detects when:\n * 1. The identifier comes from a parameter\n * 2. That parameter's function is inside a JSXExpressionContainer\n * 3. Which is a child of a JSXElement (render prop pattern)\n *\n * This is used to distinguish between:\n * - React component props: `const Modal = ({ onClose }) => ...` - should be flagged\n * - Render prop callbacks: `<MoreMenu>{close => <MenuItem onClick={close} />}</MoreMenu>` - should NOT be flagged\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns true if the identifier comes from a render prop callback parameter\n * @example\n * // Render prop callback - returns true\n * <MoreMenu>\n * {close => <MenuItem onClick={close} />}\n * </MoreMenu>\n * // isIdentifierFromRenderPropCallback(close) => true\n * @example\n * // React component prop - returns false\n * const Modal = ({ onClose }) => <button onClick={onClose} />;\n * // isIdentifierFromRenderPropCallback(onClose) => false\n */\nexport const isIdentifierFromRenderPropCallback = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): boolean => {\n // First check if it even comes from a parameter\n if (!isIdentifierFromParameter(identifier, context)) {\n return false;\n }\n\n // Get the variable that this identifier resolves to\n const scope = context.sourceCode.getScope(identifier);\n const variable = scope.references.find(ref => ref.identifier === identifier)?.resolved;\n\n if (!variable) {\n return false;\n }\n\n // Check each definition of this variable\n for (const definition of variable.defs) {\n if (definition.type !== \"Parameter\") {\n continue;\n }\n\n // Find the function that contains this parameter by walking up from the definition node\n let functionNode:\n | TSESTree.ArrowFunctionExpression\n | TSESTree.FunctionExpression\n | TSESTree.FunctionDeclaration\n | null = null;\n\n let current: TSESTree.Node | undefined = definition.node;\n do {\n if (\n current.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n current.type === AST_NODE_TYPES.FunctionExpression ||\n current.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n functionNode = current;\n break;\n }\n current = current.parent;\n } while (current !== undefined);\n\n if (!functionNode) {\n continue;\n }\n\n // Check if the function is inside a JSXExpressionContainer (render prop pattern)\n // Pattern: <Component>{callback => ...}</Component>\n const parent = functionNode.parent;\n if (parent.type === AST_NODE_TYPES.JSXExpressionContainer) {\n // Verify the JSXExpressionContainer is a child of a JSXElement\n const jsxContainerParent = parent.parent;\n if (\n jsxContainerParent.type === AST_NODE_TYPES.JSXElement ||\n jsxContainerParent.type === AST_NODE_TYPES.JSXFragment\n ) {\n return true;\n }\n }\n }\n\n return false;\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/component-utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared utilities for detecting React components and their export status in a file.\n *\n * Used by `one-component-per-file` and `component-name-matches-filename` rules.\n *\n * ## Handled patterns\n * - `export function Foo() {}`\n * - `export const Foo = () => {}`\n * - `export default function Foo() {}`\n * - `export default () => {}`\n * - `const Foo = () => {}; export { Foo }`\n * - `const Foo = () => {}; export { Foo as Bar }`\n * - `export const Foo = forwardRef(...)` / `memo(...)` (React wrapper calls)\n */\n\nimport { AST_NODE_TYPES, TSESTree } from \"@typescript-eslint/utils\";\nimport { functionReturnsJSX } from \"./ast-utils\";\n\nexport type ComponentEntry = {\n /** The name as it appears in the export (null for anonymous default exports). */\n name: string | null;\n /** The declaration node to report on (FunctionDeclaration or VariableDeclarator). */\n node: TSESTree.Node;\n};\n\nconst isComponentName = (name: string): boolean => /^[A-Z]/.test(name);\n\nconst REACT_WRAPPER_NAMES = new Set([\"memo\", \"forwardRef\"]);\n\n/**\n * Returns true only for known React higher-order component wrappers:\n * `memo(...)`, `forwardRef(...)`, `React.memo(...)`, `React.forwardRef(...)`.\n *\n * This is intentionally narrow to avoid false positives on other PascalCase\n * call expressions like `createLazyRoute(...)` or `createThemeWithBranding(...)`.\n */\nconst isReactWrapperCall = (init: TSESTree.CallExpression): boolean => {\n const { callee } = init;\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return REACT_WRAPPER_NAMES.has(callee.name);\n }\n if (callee.type === AST_NODE_TYPES.MemberExpression) {\n return (\n callee.object.type === AST_NODE_TYPES.Identifier &&\n callee.object.name === \"React\" &&\n callee.property.type === AST_NODE_TYPES.Identifier &&\n REACT_WRAPPER_NAMES.has(callee.property.name)\n );\n }\n return false;\n};\n\ntype FunctionLike = TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression;\n\nconst isFunctionLikeComponent = (fn: FunctionLike, name: string | null): boolean => {\n // Named functions are components only if PascalCase. camelCase render-function\n // callbacks (e.g. `renderFn`, `shapeEdgeLabelPortalRender`) return JSX but are\n // NOT React components and must not be flagged.\n if (name !== null) return isComponentName(name);\n // Anonymous functions: fall back to JSX-return detection (e.g. `export default () => <div />`)\n return functionReturnsJSX(fn);\n};\n\nconst isTopLevelFunctionDeclaration = (node: TSESTree.FunctionDeclaration): boolean =>\n node.parent.type === AST_NODE_TYPES.Program ||\n node.parent.type === AST_NODE_TYPES.ExportNamedDeclaration ||\n node.parent.type === AST_NODE_TYPES.ExportDefaultDeclaration;\n\nconst isTopLevelVariableDeclarator = (node: TSESTree.VariableDeclarator): boolean =>\n node.parent.parent.type === AST_NODE_TYPES.Program ||\n node.parent.parent.type === AST_NODE_TYPES.ExportNamedDeclaration;\n\n/**\n * Creates a stateful tracker that collects React component declarations and export\n * information as ESLint visits AST nodes. Call `getExportedComponents()` or\n * `getAllComponents()` inside a `Program:exit` handler once traversal is complete.\n */\nexport const createComponentFileTracker = () => {\n // component name → declaration node\n const namedComponents = new Map<string, TSESTree.Node>();\n\n // names exported inline: `export function Foo` / `export const Foo = ...`\n const inlineExportedNames = new Set<string>();\n\n // re-export specifiers: local name → exported name (`export { Foo as Bar }`)\n const reExportedNames = new Map<string, string>();\n\n // default export tracking\n let defaultExportFunctionName: string | null = null; // `export default function Foo() {}`\n let defaultExportIdentifier: string | null = null; // `export default Foo`\n let anonymousDefaultExportNode: TSESTree.Node | null = null; // `export default () => ...`\n\n return {\n onFunctionDeclaration(node: TSESTree.FunctionDeclaration) {\n if (!isTopLevelFunctionDeclaration(node)) return;\n const name = node.id?.name ?? null;\n if (!isFunctionLikeComponent(node, name)) return;\n if (name) namedComponents.set(name, node);\n if (node.parent.type === AST_NODE_TYPES.ExportDefaultDeclaration) {\n defaultExportFunctionName = name;\n }\n },\n\n onVariableDeclarator(node: TSESTree.VariableDeclarator) {\n if (!isTopLevelVariableDeclarator(node)) return;\n if (node.id.type !== AST_NODE_TYPES.Identifier) return;\n const name = node.id.name;\n const init = node.init;\n if (!init) return;\n\n if (init.type === AST_NODE_TYPES.ArrowFunctionExpression || init.type === AST_NODE_TYPES.FunctionExpression) {\n if (isFunctionLikeComponent(init, name)) {\n namedComponents.set(name, node);\n }\n } else if (init.type === AST_NODE_TYPES.CallExpression && isReactWrapperCall(init)) {\n // forwardRef / memo wrappers — always produce a component regardless of surrounding name\n namedComponents.set(name, node);\n }\n },\n\n onExportNamedDeclaration(node: TSESTree.ExportNamedDeclaration) {\n if (node.source !== null) return; // skip `export { Foo } from './other'`\n\n if (node.declaration) {\n if (node.declaration.type === AST_NODE_TYPES.FunctionDeclaration) {\n const name = node.declaration.id?.name;\n if (name) inlineExportedNames.add(name);\n } else if (node.declaration.type === AST_NODE_TYPES.VariableDeclaration) {\n for (const decl of node.declaration.declarations) {\n if (decl.id.type === AST_NODE_TYPES.Identifier) {\n inlineExportedNames.add(decl.id.name);\n }\n }\n }\n }\n\n for (const specifier of node.specifiers) {\n const localName = specifier.local.name;\n const exportedName =\n specifier.exported.type === AST_NODE_TYPES.Identifier ? specifier.exported.name : specifier.exported.value;\n reExportedNames.set(localName, exportedName);\n }\n },\n\n onExportDefaultDeclaration(node: TSESTree.ExportDefaultDeclaration) {\n const decl = node.declaration;\n\n if (decl.type === AST_NODE_TYPES.Identifier) {\n // `export default Foo` — resolved in getExportedComponents after full traversal\n defaultExportIdentifier = decl.name;\n return;\n }\n\n // Named `export default function Foo() {}` — handled by onFunctionDeclaration\n if (decl.type === AST_NODE_TYPES.FunctionDeclaration && decl.id?.name) return;\n\n if (decl.type === AST_NODE_TYPES.ArrowFunctionExpression || decl.type === AST_NODE_TYPES.FunctionExpression) {\n if (isFunctionLikeComponent(decl, null)) {\n anonymousDefaultExportNode = node;\n }\n return;\n }\n\n // Anonymous function declaration: `export default function() {}`\n if (decl.type === AST_NODE_TYPES.FunctionDeclaration && !decl.id) {\n if (isFunctionLikeComponent(decl, null)) {\n anonymousDefaultExportNode = node;\n }\n }\n },\n\n /** Returns all exported React component entries. Call from `Program:exit`. */\n getExportedComponents(): Array<ComponentEntry> {\n const result: Array<ComponentEntry> = [];\n\n for (const name of inlineExportedNames) {\n const node = namedComponents.get(name);\n if (node) result.push({ name, node });\n }\n\n for (const [localName, exportedName] of reExportedNames) {\n const node = namedComponents.get(localName);\n if (node) result.push({ name: exportedName, node });\n }\n\n if (defaultExportFunctionName !== null) {\n const node = namedComponents.get(defaultExportFunctionName);\n if (node) result.push({ name: defaultExportFunctionName, node });\n }\n\n if (defaultExportIdentifier !== null) {\n const node = namedComponents.get(defaultExportIdentifier);\n if (node) result.push({ name: defaultExportIdentifier, node });\n }\n\n if (anonymousDefaultExportNode !== null) {\n result.push({ name: null, node: anonymousDefaultExportNode });\n }\n\n return result;\n },\n\n /** Returns all top-level React component entries, exported or not. Call from `Program:exit`. */\n getAllComponents(): Array<ComponentEntry> {\n const result: Array<ComponentEntry> = [];\n for (const [name, node] of namedComponents) {\n result.push({ name, node });\n }\n if (anonymousDefaultExportNode !== null) {\n result.push({ name: null, node: anonymousDefaultExportNode });\n }\n return result;\n },\n };\n};\n"]}
@@ -0,0 +1 @@
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"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/import-utils.ts"],"names":[],"mappings":";;;AAAA,oDAA8E;AAE9E;;;;;;;;;;;;;GAaG;AAEH;;GAEG;AACH,MAAM,YAAY,GAAG,CAAC,UAAyC,EAAE,IAAgC,EAAW,EAAE;IAC5G,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,QAAQ,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAC1C,CAAC,CAAC;AAEF;;;;;;;GAOG;AACI,MAAM,qBAAqB,GAAG,CACnC,UAAyC,EACzC,WAAmB,EACqB,EAAE;IAC1C,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CACpC,CAAC,IAAI,EAAsC,EAAE,CAC3C,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,iBAAiB,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,WAAW,CACtF,CAAC;IACF,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AATW,QAAA,qBAAqB,yBAShC;AAEF;;;;;;GAMG;AACI,MAAM,mBAAmB,GAAG,CAAC,UAAsC,EAAe,EAAE;IACzF,OAAO,IAAI,GAAG,CACZ,UAAU,CAAC,UAAU;SAClB,MAAM,CAAC,CAAC,CAAC,EAAiC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,sBAAc,CAAC,eAAe,CAAC;SACvF,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAChF,MAAM,CAAC,OAAO,CAAC,CACnB,CAAC;AACJ,CAAC,CAAC;AAPW,QAAA,mBAAmB,uBAO9B;AAYF;;GAEG;AACH,MAAM,oBAAoB,GAAG,CAC3B,UAAyC,EACzC,WAAmB,EACnB,UAA4B,EAC5B,aAA0C,EAClC,EAAE;IACV,MAAM,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClE,MAAM,SAAS,GAAG,aAAa,IAAI,YAAY,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACvF,OAAO,YAAY,gBAAgB,YAAY,WAAW,IAAI,SAAS,EAAE,CAAC;AAC5E,CAAC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACI,MAAM,mBAAmB,GAAG,CAAC,OAAmC,EAA2B,EAAE;IAClG,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;IAC/E,MAAM,KAAK,GAA4B,EAAE,CAAC;IAE1C,IAAI,cAAc,EAAE,CAAC;QACnB,6BAA6B;QAC7B,MAAM,kBAAkB,GAAG,IAAA,2BAAmB,EAAC,cAAc,CAAC,CAAC;QAC/D,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,kBAAkB,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC;QAC3E,MAAM,eAAe,GAAG,oBAAoB,CAAC,UAAU,EAAE,WAAW,EAAE,kBAAkB,EAAE,cAAc,CAAC,CAAC;QAE1G,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC,CAAC;IACjE,CAAC;SAAM,CAAC;QACN,8BAA8B;QAC9B,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CACzC,CAAC,IAAI,EAAsC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,iBAAiB,CAC7F,CAAC;QAEF,IAAI,UAAU,EAAE,CAAC;YACf,kDAAkD;YAClD,MAAM,eAAe,GAAG,KAAK,oBAAoB,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC;YACrG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC;QACjE,CAAC;aAAM,CAAC;YACN,iEAAiE;YACjE,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzC,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,eAAe,GAAG,GAAG,oBAAoB,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,CAAC,MAAM,CAAC;gBAC3F,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAhCW,QAAA,mBAAmB,uBAgC9B;AAcF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACI,MAAM,gCAAgC,GAAG,CAC9C,OAAgD,EACvB,EAAE;IAC3B,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,wBAAwB,EAAE,eAAe,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;IAC/G,MAAM,KAAK,GAA4B,EAAE,CAAC;IAE1C,4EAA4E;IAC5E,MAAM,6BAA6B,GAAG,IAAA,2BAAmB,EAAC,wBAAwB,CAAC,CAAC;IACpF,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,6BAA6B,EAAE,GAAG,eAAe,CAAC,CAAC,CAAC;IAEzF,IAAI,eAAe,IAAI,eAAe,KAAK,wBAAwB,EAAE,CAAC;QACpE,0GAA0G;QAC1G,MAAM,kBAAkB,GAAG,IAAA,2BAAmB,EAAC,eAAe,CAAC,CAAC;QAChE,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,kBAAkB,EAAE,GAAG,gBAAgB,CAAC,CAAC,CAAC;QACjF,MAAM,eAAe,GAAG,oBAAoB,CAAC,UAAU,EAAE,WAAW,EAAE,kBAAkB,EAAE,eAAe,CAAC,CAAC;QAE3G,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC,CAAC;QAChE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAAC;IACrD,CAAC;SAAM,CAAC;QACN,oEAAoE;QACpE,MAAM,eAAe,GAAG,oBAAoB,CAAC,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,wBAAwB,CAAC,CAAC;QAClH,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,wBAAwB,EAAE,eAAe,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAzBW,QAAA,gCAAgC,oCAyB3C","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 * ## Helper Functions\n * - `findImportDeclaration()` - Find existing import for a package\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 * 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 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"]}
@@ -0,0 +1 @@
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"]}
@@ -0,0 +1 @@
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"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/program-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from \"path\";\nimport * as ts from \"typescript\";\nimport { findNearestFile } from \"./file-utils\";\n\n/**\n * Utility functions for building a type-checking TypeScript `Program` scoped to a library.\n *\n * ## Main Functions\n * - `getLibraryProgram()` - Build (and cache) a `ts.Program`/`ts.TypeChecker` pair for a library\n * - `clearProgramCache()` - Clear the cache. Useful for testing.\n */\n\nexport type LibraryProgram = {\n program: ts.Program;\n checker: ts.TypeChecker;\n};\n\n/**\n * Cache for library Programs to avoid re-parsing tsconfig and rebuilding the (expensive) `ts.Program`\n * on every call. Key is the resolved `projectDir` passed in, value is the built program/checker pair.\n */\nconst programCache = new Map<string, LibraryProgram>();\n\n/**\n * Nx-convention leaf tsconfigs to fall back to, in priority order, when the discovered `tsconfig.json`\n * turns out to be \"solution style\" (no real source files of its own — just `references` to these).\n */\nconst LEAF_TSCONFIG_CANDIDATES = [\"tsconfig.lib.json\", \"tsconfig.app.json\", \"tsconfig.spec.json\"];\n\n/** Parse a tsconfig file at `tsconfigPath`, resolving relative paths against its own directory. */\nconst parseTsconfigAt = (tsconfigPath: string): ts.ParsedCommandLine | null => {\n const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n\n if (configFile.error) {\n return null;\n }\n\n return ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(tsconfigPath));\n};\n\n/**\n * Resolve a tsconfig that actually covers real source files, starting from `tsconfigPath`.\n *\n * Many Nx libraries use a \"solution style\" root `tsconfig.json` (`files: []` plus `references` to\n * `tsconfig.lib.json`/`tsconfig.spec.json`/etc.) that parses to an empty `fileNames` on its own. When\n * that happens, fall back to the sibling leaf configs that actually resolve source files.\n *\n * Every usable leaf config's `fileNames` are unioned (not just the first match): `tsconfig.lib.json`\n * conventionally excludes spec/test/story/demo files, which live only in `tsconfig.spec.json`.\n * Building the Program from a single leaf would silently drop those files from type-aware scanning —\n * while the regex-based fallback elsewhere still sees them via a plain filesystem walk — leaving any\n * dynamic key referenced only from such a file neither wildcarded nor concretely expanded (i.e.\n * incorrectly reported as unused). Compiler `options` are taken from the first usable config; the\n * leaf configs share the same `extends` chain so this only affects unrelated settings like `types`.\n */\nconst resolveUsableTsconfig = (tsconfigPath: string): ts.ParsedCommandLine | null => {\n const parsed = parseTsconfigAt(tsconfigPath);\n\n if (parsed && parsed.fileNames.some(fileName => !fileName.endsWith(\".d.ts\"))) {\n return parsed;\n }\n\n const configDir = path.dirname(tsconfigPath);\n const usableConfigs: Array<ts.ParsedCommandLine> = [];\n\n for (const candidate of LEAF_TSCONFIG_CANDIDATES) {\n const candidatePath = path.join(configDir, candidate);\n\n if (!ts.sys.fileExists(candidatePath)) {\n continue;\n }\n\n const candidateParsed = parseTsconfigAt(candidatePath);\n\n if (candidateParsed && candidateParsed.fileNames.some(fileName => !fileName.endsWith(\".d.ts\"))) {\n usableConfigs.push(candidateParsed);\n }\n }\n\n const [primaryConfig, ...restConfigs] = usableConfigs;\n if (!primaryConfig) {\n return null;\n }\n\n const fileNames = new Set(primaryConfig.fileNames);\n for (const config of restConfigs) {\n for (const fileName of config.fileNames) {\n fileNames.add(fileName);\n }\n }\n\n return { ...primaryConfig, fileNames: [...fileNames] };\n};\n\n/**\n * Build (and cache) a `ts.Program` scoped to the nearest `tsconfig.json` found by walking up from\n * `projectDir`. Falls back to sibling leaf tsconfigs (`tsconfig.lib.json`, etc.) when the discovered\n * config is solution-style and covers no real source files.\n *\n * @param projectDir - Absolute path to a library's directory (or a directory inside it)\n * @returns The `Program`/`TypeChecker` pair, or `null` if no usable tsconfig was found\n * @example\n * const result = getLibraryProgram(\"/workspace/libs/my-lib\");\n * // Returns: { program, checker }\n */\nexport const getLibraryProgram = (projectDir: string): LibraryProgram | null => {\n const resolvedProjectDir = path.resolve(projectDir);\n\n const cached = programCache.get(resolvedProjectDir);\n if (cached) {\n return cached;\n }\n\n // `findNearestFile` starts looking in the *parent* of the file path it's given, so probing with a\n // synthetic file inside `resolvedProjectDir` makes it look in `resolvedProjectDir` itself first.\n const tsconfigPath = findNearestFile(path.join(resolvedProjectDir, \"__probe__.ts\"), \"tsconfig.json\");\n\n if (!tsconfigPath) {\n return null;\n }\n\n const parsedConfig = resolveUsableTsconfig(tsconfigPath);\n\n if (!parsedConfig) {\n return null;\n }\n\n const program = ts.createProgram({\n rootNames: parsedConfig.fileNames,\n options: parsedConfig.options,\n });\n\n const result: LibraryProgram = { program, checker: program.getTypeChecker() };\n\n programCache.set(resolvedProjectDir, result);\n\n return result;\n};\n\n/**\n * Clear the Program cache. Useful for testing.\n */\nexport const clearProgramCache = (): void => {\n programCache.clear();\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translation-key-types.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/translation-key-types.ts"],"names":[],"mappings":";;AAkBA,8DAWC;;AA7BD,uDAAiC;AAOjC,SAAS,yBAAyB,CAAC,IAAa;IAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC9B,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAChG,CAAC;AAED;;;;;GAKG;AACH,SAAgB,yBAAyB,CAAC,IAAa;IACrD,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QACnB,MAAM,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5G,2FAA2F;QAC3F,8FAA8F;QAC9F,MAAM,aAAa,GAAG,mBAAmB,CAAC,MAAM,GAAG,CAAC,IAAI,mBAAmB,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAE7G,OAAO,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;IACpD,CAAC;IAED,OAAO,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;AACtE,CAAC","sourcesContent":["import * as ts from \"typescript\";\n\n// Type guard for TypeScript API. Mirrors the pattern used in `typescript-utils.ts`, but\n// deliberately excludes `EnumLiteral` members: string enum members carry both the\n// `StringLiteral` and `EnumLiteral` flags, and enums are out of scope for this classifier.\ntype StringLiteralType = ts.Type & { value: string };\n\nfunction isFiniteStringLiteralType(type: ts.Type): type is StringLiteralType {\n const flags = type.getFlags();\n return (flags & ts.TypeFlags.StringLiteral) !== 0 && (flags & ts.TypeFlags.EnumLiteral) === 0;\n}\n\n/**\n * Classifies a template-literal interpolation's TypeScript type as either a finite\n * string-literal union (every possible value is statically known, e.g. `\"a\" | \"b\"`) or a\n * widened type (plain `string`, `any`, `unknown`, or any enum) whose exact set of values\n * cannot be enumerated at compile time.\n */\nexport function classifyInterpolationType(type: ts.Type): \"literalUnion\" | \"widened\" {\n if (type.isUnion()) {\n const nonUndefinedMembers = type.types.filter(member => (member.getFlags() & ts.TypeFlags.Undefined) === 0);\n // `.some(isFiniteStringLiteralType)` was previously ANDed in here too, but it's implied by\n // `length > 0 && every(...)`: if every member of a non-empty array passes, at least one does.\n const isFiniteUnion = nonUndefinedMembers.length > 0 && nonUndefinedMembers.every(isFiniteStringLiteralType);\n\n return isFiniteUnion ? \"literalUnion\" : \"widened\";\n }\n\n return isFiniteStringLiteralType(type) ? \"literalUnion\" : \"widened\";\n}\n"]}
@@ -0,0 +1 @@
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"]}