@trackunit/eslint-plugin-trackunit 0.6.108 → 0.6.110

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 +13 -0
  2. package/package.json +2 -2
  3. package/migrations/entry.js.map +0 -1
  4. package/src/index.js.map +0 -1
  5. package/src/lib/config/fragments/ignores.js.map +0 -1
  6. package/src/lib/config/fragments/import-rules.js.map +0 -1
  7. package/src/lib/config/fragments/jest-overrides.js.map +0 -1
  8. package/src/lib/config/fragments/jsdoc-rules.js.map +0 -1
  9. package/src/lib/config/fragments/module-boundaries.js.map +0 -1
  10. package/src/lib/config/fragments/no-direct-storage-access.js.map +0 -1
  11. package/src/lib/config/fragments/react-rules.js.map +0 -1
  12. package/src/lib/config/fragments/restricted-imports.js.map +0 -1
  13. package/src/lib/config/fragments/testing-library.js.map +0 -1
  14. package/src/lib/config/fragments/typescript-rules.js.map +0 -1
  15. package/src/lib/config/index.js.map +0 -1
  16. package/src/lib/config/plugins.js.map +0 -1
  17. package/src/lib/config/presets/base.js.map +0 -1
  18. package/src/lib/config/presets/e2e.js.map +0 -1
  19. package/src/lib/config/presets/react.js.map +0 -1
  20. package/src/lib/config/presets/server.js.map +0 -1
  21. package/src/lib/config/utils.js.map +0 -1
  22. package/src/lib/config-helpers/create-skip-when.js.map +0 -1
  23. package/src/lib/rules/component-name-matches-filename/component-name-matches-filename.js.map +0 -1
  24. package/src/lib/rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array.js.map +0 -1
  25. package/src/lib/rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match.js.map +0 -1
  26. package/src/lib/rules/no-deprecated-graphql-fields/no-deprecated-graphql-fields.js.map +0 -1
  27. package/src/lib/rules/no-deprecated-graphql-fields/schema-cache.js.map +0 -1
  28. package/src/lib/rules/no-dynamic-translation-key/no-dynamic-translation-key.js.map +0 -1
  29. package/src/lib/rules/no-internal-barrel-files/no-internal-barrel-files.js.map +0 -1
  30. package/src/lib/rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public.js.map +0 -1
  31. package/src/lib/rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks.js.map +0 -1
  32. package/src/lib/rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop.js.map +0 -1
  33. package/src/lib/rules/no-typescript-assertion/no-typescript-assertion.js.map +0 -1
  34. package/src/lib/rules/no-unused-translation-key/expand-dynamic-key.js.map +0 -1
  35. package/src/lib/rules/no-unused-translation-key/no-unused-translation-key.js.map +0 -1
  36. package/src/lib/rules/no-unused-translation-key/used-strings.js.map +0 -1
  37. package/src/lib/rules/one-component-per-file/one-component-per-file.js.map +0 -1
  38. package/src/lib/rules/prefer-destructured-imports/prefer-destructured-imports.js.map +0 -1
  39. package/src/lib/rules/prefer-event-specific-callback-naming/name-suggestion-strategies.js.map +0 -1
  40. package/src/lib/rules/prefer-event-specific-callback-naming/prefer-event-specific-callback-naming.js.map +0 -1
  41. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/string-based.js.map +0 -1
  42. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/type-based.js.map +0 -1
  43. package/src/lib/rules/prefer-event-specific-callback-naming/utils.js.map +0 -1
  44. package/src/lib/rules/prefer-field-components/prefer-field-components.js.map +0 -1
  45. package/src/lib/rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props.js.map +0 -1
  46. package/src/lib/rules/require-classname-alternatives/require-classname-alternatives.js.map +0 -1
  47. package/src/lib/rules/require-component-prop-contracts/require-component-prop-contracts.js.map +0 -1
  48. package/src/lib/rules/require-list-item-virtualization-props/require-list-item-virtualization-props.js.map +0 -1
  49. package/src/lib/rules/require-optional-prop-initialization/require-optional-prop-initialization.js.map +0 -1
  50. package/src/lib/rules/require-optional-prop-initialization/suggestion-utils.js.map +0 -1
  51. package/src/lib/rules/require-storybook-folder-landing-page/require-storybook-folder-landing-page.js.map +0 -1
  52. package/src/lib/rules-map.js.map +0 -1
  53. package/src/lib/utils/ast-utils.js.map +0 -1
  54. package/src/lib/utils/component-utils.js.map +0 -1
  55. package/src/lib/utils/file-utils.js.map +0 -1
  56. package/src/lib/utils/import-utils.js.map +0 -1
  57. package/src/lib/utils/nx-utils.js.map +0 -1
  58. package/src/lib/utils/package-utils.js.map +0 -1
  59. package/src/lib/utils/program-utils.js.map +0 -1
  60. package/src/lib/utils/translation-key-types.js.map +0 -1
  61. package/src/lib/utils/typescript-utils.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## 0.6.110 (2026-08-18)
2
+
3
+ ### 🧱 Updated Dependencies
4
+
5
+ - Updated css-classname-utils to 0.0.14
6
+ - Updated shared-utils to 1.16.13
7
+
8
+ ## 0.6.109 (2026-08-18)
9
+
10
+ ### 🧱 Updated Dependencies
11
+
12
+ - Updated shared-utils to 1.16.12
13
+
1
14
  ## 0.6.108 (2026-08-17)
2
15
 
3
16
  ### 🧱 Updated Dependencies
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/eslint-plugin-trackunit",
3
- "version": "0.6.108",
3
+ "version": "0.6.110",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "repository": "https://github.com/Trackunit/manager",
6
6
  "engines": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "@nx/eslint-plugin": "23.1.0",
11
- "@trackunit/css-classname-utils": "0.0.13",
11
+ "@trackunit/css-classname-utils": "0.0.14",
12
12
  "@typescript-eslint/eslint-plugin": "8.58.1",
13
13
  "@typescript-eslint/utils": "8.58.1",
14
14
  "eslint-config-prettier": "^10.1.8",
@@ -1 +0,0 @@
1
- {"version":3,"file":"entry.js","sourceRoot":"","sources":["../../../../../libs/eslint/plugin-trackunit/migrations/entry.ts"],"names":[],"mappings":"","sourcesContent":["export {};\n"]}
package/src/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/eslint/plugin-trackunit/src/index.ts"],"names":[],"mappings":";;;AAAA,+CAA2C;AAE3C,kBAAe,oBAAQ,CAAC;AAExB,uCAAuC;AAA9B,iGAAA,OAAO,OAAA;AAChB,0EAAuE;AAA9D,kHAAA,cAAc,OAAA;AACvB,4CAAsD;AAA7C,yGAAA,gBAAgB,OAAA;AAGzB,kEAAsE;AAA7D,+GAAA,gBAAgB,OAAA;AACzB,gFAAkF;AAAzE,2HAAA,qBAAqB,OAAA;AAC9B,gDAAkG;AAAzF,kGAAA,OAAO,OAAA;AAAE,gGAAA,KAAK,OAAA;AAAE,2GAAA,gBAAgB,OAAA;AAAE,6FAAA,EAAE,OAAA;AAAE,qGAAA,UAAU,OAAA;AAAE,mGAAA,QAAQ,OAAA","sourcesContent":["import { rulesMap } from \"./lib/rules-map\";\n\nexport default rulesMap;\n\nexport { configs } from \"./lib/config\";\nexport { createSkipWhen } from \"./lib/config-helpers/create-skip-when\";\nexport { findMonorepoRoot } from \"./lib/config/utils\";\nexport type { MatchCriteria, ProjectMetadata } from \"./lib/utils/nx-utils\";\n\nexport { strictJsdocRules } from \"./lib/config/fragments/jsdoc-rules\";\nexport { restrictedImportRules } from \"./lib/config/fragments/restricted-imports\";\nexport { globals, jsdoc, localRulesPlugin, nx, reactHooks, tsParser } from \"./lib/config/plugins\";\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ignores.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/fragments/ignores.ts"],"names":[],"mappings":";;;AAEa,QAAA,aAAa,GAAkB;IAC1C,OAAO,EAAE;QACP,oBAAoB;QACpB,qBAAqB;QACrB,kBAAkB;QAClB,sBAAsB;QACtB,kBAAkB;QAClB,iBAAiB;QACjB,mBAAmB;QACnB,kBAAkB;QAClB,4BAA4B;QAC5B,uBAAuB;QACvB,cAAc;QACd,eAAe;KAChB;CACF,CAAC","sourcesContent":["import type { Linter } from \"eslint\";\n\nexport const globalIgnores: Linter.Config = {\n ignores: [\n \"**/src/gql-api.tsx\",\n \"**/src/typings/**/*\",\n \"**/testUtils.tsx\",\n \"**/webpack.config.js\",\n \"**/jest.config.*\",\n \"**/jest.setup.*\",\n \"**/vite*.config.*\",\n \"**/vite*.setup.*\",\n \"**/src/**/generated/**/*.*\",\n \"**/src/**/generated.*\",\n \"**/dist/**/*\",\n \"**/*.docs.mdx\",\n ],\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"import-rules.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/fragments/import-rules.ts"],"names":[],"mappings":";;;AACA,4EAAuE;AACvE,wCAA0C;AAE7B,QAAA,WAAW,GAAuB;IAC7C,mBAAmB,EAAE;QACnB,OAAO;QACP;YACE,cAAc,EAAE,IAAI;SACrB;KACF;IACD,gBAAgB,EAAE,KAAK;CACxB,CAAC;AAEK,MAAM,wCAAwC,GAAG,CAAC,OAAe,EAAiB,EAAE,CACzF,IAAA,iCAAc,EAAC;IACb,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE;IAC9B,OAAO,EAAE;QACP,UAAU,EAAE,sBAAY;KACzB;IACD,KAAK,EAAE;QACL,qCAAqC,EAAE;YACrC,OAAO;YACP;gBACE,UAAU,EAAE,OAAO;gBACnB,eAAe,EAAE;oBACf,oBAAoB;oBACpB,oBAAoB;oBACpB,iBAAiB;oBACjB,iBAAiB;oBACjB,mBAAmB;oBACnB,YAAY;oBACZ,aAAa;oBACb,eAAe;oBACf,kBAAkB;oBAClB,kBAAkB;oBAClB,iBAAiB;oBACjB,iBAAiB;oBACjB,mBAAmB;oBACnB,0BAA0B;oBAC1B,uBAAuB;oBACvB,4BAA4B;oBAC5B,kBAAkB;oBAClB,eAAe;oBACf,aAAa;oBACb,6BAA6B;oBAC7B,oBAAoB;oBACpB,6CAA6C;oBAC7C,4BAA4B;iBAC7B;gBACD,oBAAoB,EAAE,KAAK;gBAC3B,gBAAgB,EAAE,IAAI;gBACtB,mBAAmB,EAAE,IAAI;aAC1B;SACF;KACF;CACF,CAAC,CAAC;AA1CQ,QAAA,wCAAwC,4CA0ChD","sourcesContent":["import type { Linter } from \"eslint\";\nimport { createSkipWhen } from \"../../config-helpers/create-skip-when\";\nimport { importPlugin } from \"../plugins\";\n\nexport const importRules: Linter.RulesRecord = {\n \"import-x/no-cycle\": [\n \"error\",\n {\n ignoreExternal: true,\n },\n ],\n \"import-x/first\": \"off\",\n};\n\nexport const createImportExtraneousDependenciesConfig = (rootDir: string): Linter.Config =>\n createSkipWhen({\n when: { tags: [\"scope:tool\"] },\n plugins: {\n \"import-x\": importPlugin,\n },\n rules: {\n \"import-x/no-extraneous-dependencies\": [\n \"error\",\n {\n packageDir: rootDir,\n devDependencies: [\n \"**/*.spec.{ts,tsx}\",\n \"**/*.test.{ts,tsx}\",\n \"**/jest.setup.*\",\n \"**/vite.setup.*\",\n \"**/vite.config.ts\",\n \"**/test/**\",\n \"**/tests/**\",\n \"**/testing/**\",\n \"**/test-setup/**\",\n \"**/test-utils/**\",\n \"**/__tests__/**\",\n \"**/__mocks__/**\",\n \"**/mocks.{ts,tsx}\",\n \"**/core-contexts-test/**\",\n \"**/*.stories.{ts,tsx}\",\n \"**/storybookUtils.{ts,tsx}\",\n \"**/.storybook/**\",\n \"**/scripts/**\",\n \"**/tools/**\",\n \"**/*.config.{ts,js,cjs,mjs}\",\n \"**/css/tailwind/**\",\n \"**/css/tailwind-custom-properties-plugin/**\",\n \"**/css/component-tokens/**\",\n ],\n optionalDependencies: false,\n peerDependencies: true,\n bundledDependencies: true,\n },\n ],\n },\n });\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"jest-overrides.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/fragments/jest-overrides.ts"],"names":[],"mappings":";;;AACA,wCAAkD;AAErC,QAAA,iBAAiB,GAAkB;IAC9C,KAAK,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;IACxC,eAAe,EAAE;QACf,WAAW,EAAE,CAAC;QACd,UAAU,EAAE,QAAQ;QACpB,aAAa,EAAE;YACb,OAAO,EAAE,CAAC,oBAAoB,CAAC;SAChC;KACF;IAED,OAAO,EAAE;QACP,IAAI,EAAJ,cAAI;QACJ,iBAAiB,EAAE,wBAAc;KAClC;IAED,KAAK,EAAE;QACL,GAAG,cAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK;QACjC,GAAG,cAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK;QAC3B,oCAAoC,EAAE,KAAK;QAC3C,sCAAsC,EAAE,KAAK;QAC7C,0CAA0C,EAAE,KAAK;QACjD,oCAAoC,EAAE,KAAK;QAC3C,oDAAoD,EAAE,OAAO;QAC7D,YAAY,EAAE,KAAK;QACnB,uBAAuB,EAAE,KAAK;QAC9B,0BAA0B,EAAE,KAAK;QACjC,+CAA+C,EAAE,KAAK;KACvD;CACF,CAAC","sourcesContent":["import type { Linter } from \"eslint\";\nimport { jest, testingLibrary } from \"../plugins\";\n\nexport const baseJestOverrides: Linter.Config = {\n files: [\"**/*.spec.ts\", \"**/*.spec.tsx\"],\n languageOptions: {\n ecmaVersion: 5,\n sourceType: \"script\",\n parserOptions: {\n project: [\"./tsconfig.*?.json\"],\n },\n },\n\n plugins: {\n jest,\n \"testing-library\": testingLibrary,\n },\n\n rules: {\n ...jest.configs.recommended.rules,\n ...jest.configs.style.rules,\n \"@typescript-eslint/no-explicit-any\": \"off\",\n \"@typescript-eslint/no-empty-function\": \"off\",\n \"@typescript-eslint/no-non-null-assertion\": \"off\",\n \"@trackunit/no-typescript-assertion\": \"off\",\n \"@trackunit/no-jest-mock-trackunit-react-core-hooks\": \"error\",\n \"no-console\": \"off\",\n \"no-restricted-globals\": \"off\",\n \"no-restricted-properties\": \"off\",\n \"@typescript-eslint/strict-boolean-expressions\": \"off\",\n },\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"jsdoc-rules.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/fragments/jsdoc-rules.ts"],"names":[],"mappings":";;;AAEa,QAAA,eAAe,GAAuB;IACjD,iBAAiB,EAAE;QACjB,OAAO;QACP,OAAO;QACP;YACE,UAAU,EAAE,CAAC;SACd;KACF;IACD,uBAAuB,EAAE,OAAO;IAChC,wBAAwB,EAAE,KAAK;IAC/B,yBAAyB,EAAE,KAAK;IAChC,4BAA4B,EAAE;QAC5B,OAAO;QACP;YACE,QAAQ,EAAE;gBACR;oBACE,OAAO,EAAE,sCAAsC;oBAC/C,OAAO,EAAE,KAAK;oBACd,OAAO,EAAE,qDAAqD;iBAC/D;aACF;SACF;KACF;CACF,CAAC;AAEW,QAAA,gBAAgB,GAAuB;IAClD,qBAAqB,EAAE;QACrB,OAAO;QACP;YACE,UAAU,EAAE,IAAI;YAEhB,OAAO,EAAE;gBACP,uBAAuB,EAAE,IAAI;gBAC7B,gBAAgB,EAAE,IAAI;gBACtB,mBAAmB,EAAE,IAAI;gBACzB,kBAAkB,EAAE,IAAI;gBACxB,gBAAgB,EAAE,IAAI;aACvB;SACF;KACF;IAED,0BAA0B,EAAE;QAC1B,OAAO;QACP;YACE,YAAY,EAAE,CAAC,KAAK,CAAC;SACtB;KACF;IAED,yBAAyB,EAAE,OAAO;IAClC,4BAA4B,EAAE,OAAO;IACrC,mBAAmB,EAAE,OAAO;IAC5B,iCAAiC,EAAE,OAAO;IAC1C,oBAAoB,EAAE,OAAO;IAC7B,4BAA4B,EAAE,OAAO;IACrC,wFAAwF;IACxF,0FAA0F;IAC1F,uFAAuF;IACvF,uBAAuB,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC;IAClE,mBAAmB,EAAE,OAAO;IAC5B,oBAAoB,EAAE,OAAO;IAC7B,uBAAuB,EAAE,OAAO;IAChC,kBAAkB,EAAE,OAAO;IAC3B,6BAA6B,EAAE,OAAO;IACtC,wBAAwB,EAAE,OAAO;IACjC,0BAA0B,EAAE,OAAO;IACnC,wBAAwB,EAAE,OAAO;IACjC,oCAAoC,EAAE,OAAO;IAC7C,6BAA6B,EAAE,OAAO;IACtC,6BAA6B,EAAE,OAAO;IACtC,6BAA6B,EAAE,OAAO;IACtC,mCAAmC,EAAE,OAAO;IAC5C,sBAAsB,EAAE,OAAO;IAC/B,4BAA4B,EAAE,OAAO;CACtC,CAAC","sourcesContent":["import type { Linter } from \"eslint\";\n\nexport const basicJsdocRules: Linter.RulesRecord = {\n \"jsdoc/tag-lines\": [\n \"error\",\n \"never\",\n {\n startLines: 1,\n },\n ],\n \"jsdoc/check-alignment\": \"error\",\n \"prefer-arrow-functions\": \"off\",\n \"jsdoc/check-indentation\": \"off\",\n \"jsdoc/no-restricted-syntax\": [\n \"error\",\n {\n contexts: [\n {\n comment: \"JsdocBlock:has(JsdocTag[tag=/type/])\",\n context: \"any\",\n message: \"Projects should not use @type annotation in JSDocs.\",\n },\n ],\n },\n ],\n};\n\nexport const strictJsdocRules: Linter.RulesRecord = {\n \"jsdoc/require-jsdoc\": [\n \"error\",\n {\n publicOnly: true,\n\n require: {\n ArrowFunctionExpression: true,\n ClassDeclaration: true,\n FunctionDeclaration: true,\n FunctionExpression: true,\n MethodDefinition: true,\n },\n },\n ],\n\n \"jsdoc/no-undefined-types\": [\n \"error\",\n {\n definedTypes: [\"JSX\"],\n },\n ],\n\n \"jsdoc/check-param-names\": \"error\",\n \"jsdoc/require-returns-type\": \"error\",\n \"jsdoc/valid-types\": \"error\",\n \"jsdoc/require-param-description\": \"error\",\n \"jsdoc/check-access\": \"error\",\n \"jsdoc/check-property-names\": \"error\",\n // `important` is GLU-1348's docgen-enricher annotation vocabulary (alongside `@expand`,\n // `@category`, and `@ignore`, which are already recognized TypeDoc/JSDoc tags and need no\n // allowlisting here) — see `libs/storybook/docgen-enricher`'s `AnnotationTags` schema.\n \"jsdoc/check-tag-names\": [\"error\", { definedTags: [\"important\"] }],\n \"jsdoc/check-types\": \"error\",\n \"jsdoc/check-values\": \"error\",\n \"jsdoc/check-alignment\": \"error\",\n \"jsdoc/empty-tags\": \"error\",\n \"jsdoc/implements-on-classes\": \"error\",\n \"jsdoc/multiline-blocks\": \"error\",\n \"jsdoc/no-multi-asterisks\": \"error\",\n \"jsdoc/require-property\": \"error\",\n \"jsdoc/require-property-description\": \"error\",\n \"jsdoc/require-property-name\": \"error\",\n \"jsdoc/require-property-type\": \"error\",\n \"jsdoc/require-returns-check\": \"error\",\n \"jsdoc/require-returns-description\": \"error\",\n \"jsdoc/require-yields\": \"error\",\n \"jsdoc/require-yields-check\": \"error\",\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"module-boundaries.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/fragments/module-boundaries.ts"],"names":[],"mappings":";;;AAEa,QAAA,mBAAmB,GAAuB;IACrD,+BAA+B,EAAE;QAC/B,OAAO;QACP;YACE,KAAK,EAAE,EAAE;YAET,cAAc,EAAE;gBACd;oBACE,SAAS,EAAE,UAAU;oBACrB,wBAAwB,EAAE,CAAC,gBAAgB,EAAE,YAAY,EAAE,cAAc,CAAC;oBAC1E,qBAAqB,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC;iBACpD;gBACD;oBACE,SAAS,EAAE,gBAAgB;oBAC3B,wBAAwB,EAAE,CAAC,YAAY,EAAE,cAAc,CAAC;oBACxD,qBAAqB,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC;iBACpD;gBACD;oBACE,SAAS,EAAE,YAAY;oBACvB,wBAAwB,EAAE,CAAC,YAAY,EAAE,cAAc,CAAC;oBACxD,qBAAqB,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC;iBACpD;gBACD;oBACE,SAAS,EAAE,cAAc;oBACzB,wBAAwB,EAAE,CAAC,cAAc,CAAC;oBAC1C,qBAAqB,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC;iBAC7C;gBACD;oBACE,SAAS,EAAE,WAAW;oBACtB,wBAAwB,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC;iBAC3D;gBACD;oBACE,SAAS,EAAE,cAAc;oBACzB,wBAAwB,EAAE,CAAC,cAAc,CAAC;iBAC3C;gBACD;oBACE,SAAS,EAAE,YAAY;oBACvB,wBAAwB,EAAE,CAAC,YAAY,CAAC;iBACzC;gBACD;oBACE,SAAS,EAAE,cAAc;oBACzB,wBAAwB,EAAE,CAAC,cAAc,CAAC;iBAC3C;gBACD;oBACE,SAAS,EAAE,iBAAiB;oBAC5B,wBAAwB,EAAE,CAAC,iBAAiB,EAAE,mBAAmB,CAAC;iBACnE;gBACD;oBACE,SAAS,EAAE,qBAAqB;oBAChC,wBAAwB,EAAE,CAAC,qBAAqB,EAAE,mBAAmB,CAAC;iBACvE;gBACD;oBACE,SAAS,EAAE,mBAAmB;oBAC9B,wBAAwB,EAAE,CAAC,mBAAmB,CAAC;iBAChD;gBACD;oBACE,SAAS,EAAE,4BAA4B;oBACvC,uBAAuB,EAAE,CAAC,YAAY,CAAC;iBACxC;gBACD;oBACE,SAAS,EAAE,cAAc;iBAC1B;gBACD;oBACE,SAAS,EAAE,YAAY;iBACxB;gBACD;oBACE,SAAS,EAAE,OAAO;iBACnB;gBACD;oBACE,SAAS,EAAE,OAAO;iBACnB;gBACD;oBACE,SAAS,EAAE,OAAO;iBACnB;gBACD;oBACE,SAAS,EAAE,OAAO;iBACnB;gBACD;oBACE,SAAS,EAAE,aAAa;oBACxB,wBAAwB,EAAE,CAAC,aAAa,CAAC;oBACzC,qBAAqB,EAAE,CAAC,WAAW,CAAC;oBACpC,uBAAuB,EAAE,CAAC,YAAY,CAAC;iBACxC;aACF;YAED,6BAA6B,EAAE,IAAI;YACnC,yBAAyB,EAAE,IAAI;SAChC;KACF;CACF,CAAC","sourcesContent":["import type { Linter } from \"eslint\";\n\nexport const moduleBoundaryRules: Linter.RulesRecord = {\n \"@nx/enforce-module-boundaries\": [\n \"error\",\n {\n allow: [],\n\n depConstraints: [\n {\n sourceTag: \"type:app\",\n onlyDependOnLibsWithTags: [\"type:extension\", \"type:react\", \"type:vanilla\"],\n bannedExternalImports: [\"i18next\", \"react-i18next\"],\n },\n {\n sourceTag: \"type:extension\",\n onlyDependOnLibsWithTags: [\"type:react\", \"type:vanilla\"],\n bannedExternalImports: [\"i18next\", \"react-i18next\"],\n },\n {\n sourceTag: \"type:react\",\n onlyDependOnLibsWithTags: [\"type:react\", \"type:vanilla\"],\n bannedExternalImports: [\"i18next\", \"react-i18next\"],\n },\n {\n sourceTag: \"type:vanilla\",\n onlyDependOnLibsWithTags: [\"type:vanilla\"],\n bannedExternalImports: [\"i18next\", \"react*\"],\n },\n {\n sourceTag: \"scope:app\",\n onlyDependOnLibsWithTags: [\"scope:client\", \"scope:server\"],\n },\n {\n sourceTag: \"scope:client\",\n onlyDependOnLibsWithTags: [\"scope:client\"],\n },\n {\n sourceTag: \"scope:tool\",\n onlyDependOnLibsWithTags: [\"scope:tool\"],\n },\n {\n sourceTag: \"scope:server\",\n onlyDependOnLibsWithTags: [\"scope:server\"],\n },\n {\n sourceTag: \"visibility:host\",\n onlyDependOnLibsWithTags: [\"visibility:host\", \"visibility:shared\"],\n },\n {\n sourceTag: \"visibility:iris-app\",\n onlyDependOnLibsWithTags: [\"visibility:iris-app\", \"visibility:shared\"],\n },\n {\n sourceTag: \"visibility:shared\",\n onlyDependOnLibsWithTags: [\"visibility:shared\"],\n },\n {\n sourceTag: \"dependencies:no-deprecated\",\n notDependOnLibsWithTags: [\"deprecated\"],\n },\n {\n sourceTag: \"gql:internal\",\n },\n {\n sourceTag: \"gql:public\",\n },\n {\n sourceTag: \"tier1\",\n },\n {\n sourceTag: \"tier2\",\n },\n {\n sourceTag: \"tier3\",\n },\n {\n sourceTag: \"tier4\",\n },\n {\n sourceTag: \"publish:npm\",\n onlyDependOnLibsWithTags: [\"publish:npm\"],\n bannedExternalImports: [\"@sentry/*\"],\n notDependOnLibsWithTags: [\"deprecated\"],\n },\n ],\n\n enforceBuildableLibDependency: true,\n banTransitiveDependencies: true,\n },\n ],\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-direct-storage-access.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/fragments/no-direct-storage-access.ts"],"names":[],"mappings":";;;AACA,oCAA4C;AAE5C,MAAM,mBAAmB,GACvB,uHAAuH,CAAC;AAC1H,MAAM,qBAAqB,GACzB,6HAA6H,CAAC;AAEnH,QAAA,0BAA0B,GAAqB;IAC1D,OAAO;IACP;QACE,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,mBAAmB;KAC7B;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,qBAAqB;KAC/B;CACF,CAAC;AAEW,QAAA,6BAA6B,GAAqB;IAC7D,OAAO;IACP;QACE,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,cAAc;QACxB,OAAO,EAAE,mBAAmB;KAC7B;IACD;QACE,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,gBAAgB;QAC1B,OAAO,EAAE,qBAAqB;KAC/B;IACD;QACE,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,cAAc;QACxB,OAAO,EAAE,mBAAmB;KAC7B;IACD;QACE,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,gBAAgB;QAC1B,OAAO,EAAE,qBAAqB;KAC/B;CACF,CAAC;AAEF,MAAM,8BAA8B,GAAG;IACrC,iEAAiE;IACjE,wEAAwE;IACxE,mEAAmE;IACnE,0EAA0E;IAC1E,6DAA6D;CAC9D,CAAC;AAEW,QAAA,yCAAyC,GAAkB;IACtE,QAAQ,EAAE,IAAA,wBAAgB,GAAE;IAC5B,KAAK,EAAE,8BAA8B;IACrC,KAAK,EAAE;QACL,0BAA0B,EAAE,KAAK;KAClC;CACF,CAAC;AAEF,4FAA4F;AAC5F,sFAAsF;AACtF,2FAA2F;AAC3F,+FAA+F;AAC/F,MAAM,iCAAiC,GAAG;IACxC,oFAAoF;IACpF,8EAA8E;IAC9E,uFAAuF;IACvF,0FAA0F;IAC1F,6FAA6F;IAC7F,6FAA6F;IAC7F,6CAA6C;CAC9C,CAAC;AAEW,QAAA,wCAAwC,GAAkB;IACrE,QAAQ,EAAE,IAAA,wBAAgB,GAAE;IAC5B,KAAK,EAAE,iCAAiC;IACxC,KAAK,EAAE;QACL,uBAAuB,EAAE,KAAK;KAC/B;CACF,CAAC","sourcesContent":["import type { Linter } from \"eslint\";\nimport { findMonorepoRoot } from \"../utils\";\n\nconst localStorageMessage =\n \"Use useLocalStorage or useLocalStorageReducer from @trackunit/react-components instead of direct localStorage access.\";\nconst sessionStorageMessage =\n \"Use useSessionStorage or useSessionStorageReducer from @trackunit/react-components instead of direct sessionStorage access.\";\n\nexport const noDirectStorageGlobalsRule: Linter.RuleEntry = [\n \"error\",\n {\n name: \"localStorage\",\n message: localStorageMessage,\n },\n {\n name: \"sessionStorage\",\n message: sessionStorageMessage,\n },\n];\n\nexport const noDirectStoragePropertiesRule: Linter.RuleEntry = [\n \"error\",\n {\n object: \"window\",\n property: \"localStorage\",\n message: localStorageMessage,\n },\n {\n object: \"window\",\n property: \"sessionStorage\",\n message: sessionStorageMessage,\n },\n {\n object: \"globalThis\",\n property: \"localStorage\",\n message: localStorageMessage,\n },\n {\n object: \"globalThis\",\n property: \"sessionStorage\",\n message: sessionStorageMessage,\n },\n];\n\nconst storageHookImplementationFiles = [\n \"libs/react/components/src/hooks/localStorage/useLocalStorage.ts\",\n \"libs/react/components/src/hooks/localStorage/useLocalStorageReducer.ts\",\n \"libs/react/components/src/hooks/localStorage/useSessionStorage.ts\",\n \"libs/react/components/src/hooks/localStorage/useSessionStorageReducer.ts\",\n \"libs/shared/utils/src/localStorage/localStorageAccessors.ts\",\n];\n\nexport const noDirectStoragePropertyExceptionOverrides: Linter.Config = {\n basePath: findMonorepoRoot(),\n files: storageHookImplementationFiles,\n rules: {\n \"no-restricted-properties\": \"off\",\n },\n};\n\n// Files exempted from the bare `localStorage`/`sessionStorage` globals check (as opposed to\n// `window.localStorage`, covered by noDirectStoragePropertyExceptionOverrides above).\n// Deliberately narrow: only for bundles where pulling in the shared storage helpers' zod +\n// superjson runtime is itself the problem, not a call site that merely predates the migration.\nconst directStorageGlobalExceptionFiles = [\n // A <script defer> loaded synchronously in the <head> of every Iris app iframe (see\n // libs/iris-app-sdk/iris-app-build-utilities/src/plugin-shared/index.html and\n // apps/iris-app-sdk-server/src/app/iris-app-content.ts). Routing its two-number reload\n // guard through readLocalStorageValue/writeLocalStorageValue pulls zod and superjson into\n // this bundle, roughly 4x'ing its size (measured ~31.9 KB -> ~128.6 KB raw, ~9.4 KB -> ~30.4\n // KB gzip) for every one of the ~118 Iris apps' iframe boots — not worth it for two numbers.\n \"apps/iris-app-loader/src/iris-app-loader.ts\",\n];\n\nexport const noDirectStorageGlobalsExceptionOverrides: Linter.Config = {\n basePath: findMonorepoRoot(),\n files: directStorageGlobalExceptionFiles,\n rules: {\n \"no-restricted-globals\": \"off\",\n },\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"react-rules.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/fragments/react-rules.ts"],"names":[],"mappings":";;;AAEa,QAAA,UAAU,GAAuB;IAC5C,4BAA4B,EAAE,OAAO;IACrC,6BAA6B,EAAE,OAAO;IAEtC,oBAAoB,EAAE,OAAO;IAC7B,8BAA8B,EAAE,OAAO;IACvC,sCAAsC,EAAE,OAAO;IAC/C,oBAAoB,EAAE,OAAO;IAC7B,qBAAqB,EAAE,OAAO;IAC9B,iCAAiC,EAAE,OAAO;IAC1C,sBAAsB,EAAE,OAAO;IAC/B,yBAAyB,EAAE,OAAO;IAClC,gCAAgC,EAAE,OAAO;IACzC,+BAA+B,EAAE,OAAO;IACxC,oBAAoB,EAAE,OAAO;IAE7B,0BAA0B,EAAE,OAAO;IACnC,qCAAqC,EAAE,MAAM;IAC7C,kBAAkB,EAAE,MAAM;IAC1B,iCAAiC,EAAE,MAAM;IACzC,yCAAyC,EAAE,MAAM;IACjD,kCAAkC,EAAE,MAAM;IAE1C,gCAAgC,EAAE;QAChC,OAAO;QACP;YACE,QAAQ,EAAE,OAAO;YACjB,iBAAiB,EAAE,QAAQ;YAC3B,KAAK,EAAE,OAAO;SACf;KACF;IAED,eAAe,EAAE,OAAO;IACxB,4BAA4B,EAAE,OAAO;IACrC,sBAAsB,EAAE,OAAO;IAC/B,qBAAqB,EAAE,OAAO;IAC9B,iBAAiB,EAAE,OAAO;IAC1B,4BAA4B,EAAE,OAAO;IACrC,sBAAsB,EAAE,OAAO;IAE/B,wBAAwB,EAAE;QACxB,OAAO;QACP;YACE,cAAc,EAAE,KAAK;SACtB;KACF;CACF,CAAC;AAEW,QAAA,gBAAgB,GAAuB;IAClD,kDAAkD,EAAE,OAAO;IAC3D,2CAA2C,EAAE;QAC3C,OAAO;QACP;YACE,YAAY,EAAE;gBACZ,KAAK,EAAE,CAAC,SAAS,CAAC;gBAClB,IAAI,EAAE,CAAC,SAAS,CAAC;gBACjB,IAAI,EAAE,CAAC,SAAS,CAAC;gBACjB,KAAK,EAAE,CAAC,SAAS,CAAC;gBAClB,IAAI,EAAE,CAAC,MAAM,CAAC;gBACd,MAAM,EAAE,CAAC,QAAQ,CAAC;gBAClB,OAAO,EAAE,CAAC,MAAM,CAAC;gBACjB,GAAG,EAAE,CAAC,QAAQ,CAAC;gBACf,MAAM,EAAE,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,CAAC,SAAS,CAAC;gBAClB,OAAO,EAAE,CAAC,SAAS,CAAC;gBACpB,KAAK,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC;gBACjC,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC;gBACxB,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC;gBAChD,MAAM,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC;gBAC7B,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC;aACzB;YACD,QAAQ,EAAE;gBACR,IAAI;gBACJ,MAAM;gBACN,QAAQ;gBACR,UAAU;gBACV,UAAU;gBACV,UAAU;gBACV,UAAU;gBACV,UAAU;gBACV,UAAU;gBACV,MAAM;gBACN,aAAa;gBACb,SAAS;gBACT,QAAQ;gBACR,QAAQ;gBACR,QAAQ;gBACR,OAAO;gBACP,MAAM;gBACN,QAAQ;gBACR,YAAY;gBACZ,aAAa;gBACb,MAAM;gBACN,KAAK;gBACL,IAAI;aACL;SACF;KACF;IACD,mDAAmD,EAAE,OAAO;IAC5D,4CAA4C,EAAE,OAAO;IACrD,oDAAoD,EAAE,OAAO;IAC7D,wCAAwC,EAAE;QACxC,OAAO;QACP;YACE,QAAQ,EAAE;gBACR,KAAK,EAAE,OAAO;aACf;SACF;KACF;IACD,iDAAiD,EAAE,OAAO;IAC1D,kDAAkD,EAAE;QAClD,OAAO;QACP;YACE,MAAM,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,eAAe,CAAC;SACjD;KACF;IACD,sDAAsD,EAAE;QACtD,OAAO;QACP;YACE,YAAY,EAAE,CAAC,cAAc,CAAC;SAC/B;KACF;IACD,oCAAoC,EAAE,OAAO;IAC7C,mCAAmC,EAAE,OAAO;IAC5C,4CAA4C,EAAE;QAC5C,MAAM;QACN;YACE,iBAAiB,EAAE;gBACjB,gFAAgF;gBAChF,mDAAmD;gBACnD,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE;gBAC3C,mFAAmF;gBACnF,kFAAkF;gBAClF,6CAA6C;gBAC7C,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE;aAC7C;SACF;KACF;CACF,CAAC;AAEW,QAAA,4BAA4B,GAAkB;IACzD,KAAK,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;IACxC,KAAK,EAAE;QACL,6BAA6B,EAAE,OAAO;QACtC,oBAAoB,EAAE,OAAO;KAC9B;CACF,CAAC;AAEW,QAAA,mBAAmB,GAAkB;IAChD,KAAK,EAAE,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;IAC9C,KAAK,EAAE;QACL,qBAAqB,EAAE,KAAK;QAC5B,YAAY,EAAE,KAAK;QACnB,sCAAsC,EAAE,KAAK;KAC9C;CACF,CAAC","sourcesContent":["import type { Linter } from \"eslint\";\n\nexport const reactRules: Linter.RulesRecord = {\n \"react-hooks/rules-of-hooks\": \"error\",\n \"react-hooks/exhaustive-deps\": \"error\",\n\n \"react-hooks/config\": \"error\",\n \"react-hooks/error-boundaries\": \"error\",\n \"react-hooks/component-hook-factories\": \"error\",\n \"react-hooks/gating\": \"error\",\n \"react-hooks/globals\": \"error\",\n \"react-hooks/set-state-in-render\": \"error\",\n \"react-hooks/use-memo\": \"error\",\n \"react/self-closing-comp\": \"error\",\n \"react-hooks/unsupported-syntax\": \"error\",\n \"react-hooks/static-components\": \"error\",\n \"react-hooks/purity\": \"error\",\n\n \"react-hooks/immutability\": \"error\",\n \"react/no-unstable-nested-components\": \"warn\",\n \"react-hooks/refs\": \"warn\",\n \"react-hooks/set-state-in-effect\": \"warn\",\n \"react-hooks/preserve-manual-memoization\": \"warn\",\n \"react-hooks/incompatible-library\": \"warn\",\n\n \"react/jsx-curly-brace-presence\": [\n \"error\",\n {\n children: \"never\",\n propElementValues: \"always\",\n props: \"never\",\n },\n ],\n\n \"react/jsx-key\": \"error\",\n \"react/jsx-no-leaked-render\": \"error\",\n \"react/jsx-uses-react\": \"error\",\n \"react/jsx-uses-vars\": \"error\",\n \"react/no-danger\": \"error\",\n \"react/no-unused-prop-types\": \"error\",\n \"react/jsx-sort-props\": \"error\",\n\n \"react/no-children-prop\": [\n \"error\",\n {\n allowFunctions: false,\n },\n ],\n};\n\nexport const reactCustomRules: Linter.RulesRecord = {\n \"@trackunit/no-template-strings-in-classname-prop\": \"error\",\n \"@trackunit/require-classname-alternatives\": [\n \"error\",\n {\n alternatives: {\n slate: [\"neutral\"],\n gray: [\"neutral\"],\n zinc: [\"neutral\"],\n stone: [\"neutral\"],\n teal: [\"cyan\"],\n purple: [\"violet\"],\n fuchsia: [\"pink\"],\n red: [\"danger\"],\n yellow: [\"warning\"],\n green: [\"success\"],\n emerald: [\"success\"],\n amber: [\"warning\", \"low\", \"idle\"],\n sky: [\"primary\", \"info\"],\n blue: [\"primary\", \"info\", \"working\", \"utilized\"],\n indigo: [\"primary\", \"violet\"],\n rose: [\"danger\", \"pink\"],\n },\n prefixes: [\n \"bg\",\n \"text\",\n \"border\",\n \"border-t\",\n \"border-r\",\n \"border-b\",\n \"border-l\",\n \"border-x\",\n \"border-y\",\n \"ring\",\n \"ring-offset\",\n \"outline\",\n \"divide\",\n \"shadow\",\n \"accent\",\n \"caret\",\n \"fill\",\n \"stroke\",\n \"decoration\",\n \"placeholder\",\n \"from\",\n \"via\",\n \"to\",\n ],\n },\n ],\n \"@trackunit/require-list-item-virtualization-props\": \"error\",\n \"@trackunit/cva-merge-base-classes-as-array\": \"error\",\n \"@trackunit/design-guideline-button-icon-size-match\": \"error\",\n \"@trackunit/prefer-destructured-imports\": [\n \"error\",\n {\n packages: {\n react: \"React\",\n },\n },\n ],\n \"@trackunit/require-optional-prop-initialization\": \"error\",\n \"@trackunit/prefer-event-specific-callback-naming\": [\n \"error\",\n {\n events: [\"onClick\", \"onSubmit\", \"onDoubleClick\"],\n },\n ],\n \"@trackunit/prefer-mouse-event-handler-in-react-props\": [\n \"error\",\n {\n allowedNames: [\"onClickClose\"],\n },\n ],\n \"@trackunit/prefer-field-components\": \"error\",\n \"@trackunit/one-component-per-file\": \"error\",\n \"@trackunit/component-name-matches-filename\": [\n \"warn\",\n {\n allowedMismatches: [\n // i18next convention: every library's translation.tsx exports a `Trans` wrapper\n // named after the library component, not the file.\n { file: \"translation\", component: \"Trans\" },\n // React context pattern: *Context files always contain both the context object and\n // the provider component. The provider can't be renamed to match the file because\n // the context object already uses that name.\n { file: \"*Context\", component: \"*Provider\" },\n ],\n },\n ],\n};\n\nexport const reactTestingLibraryOverrides: Linter.Config = {\n files: [\"**/*.spec.ts\", \"**/*.spec.tsx\"],\n rules: {\n \"jest/no-commented-out-tests\": \"error\",\n \"jest/expect-expect\": \"error\",\n },\n};\n\nexport const reactStoryOverrides: Linter.Config = {\n files: [\"**/*.stories.ts\", \"**/*.stories.tsx\"],\n rules: {\n \"jsdoc/require-jsdoc\": \"off\",\n \"no-console\": \"off\",\n \"@typescript-eslint/no-empty-function\": \"off\",\n },\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"restricted-imports.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/fragments/restricted-imports.ts"],"names":[],"mappings":";;;AAEa,QAAA,qBAAqB,GAAuB;IACvD,uBAAuB,EAAE;QACvB,OAAO;QACP;YACE,KAAK,EAAE;gBACL;oBACE,IAAI,EAAE,sBAAsB;oBAC5B,OAAO,EAAE,2DAA2D;iBACrE;gBACD;oBACE,IAAI,EAAE,eAAe;oBACrB,WAAW,EAAE,CAAC,gBAAgB,CAAC;oBAC/B,OAAO,EAAE,gFAAgF;iBAC1F;gBACD;oBACE,IAAI,EAAE,eAAe;oBACrB,WAAW,EAAE,CAAC,OAAO,CAAC;oBACtB,OAAO,EAAE,uEAAuE;iBACjF;gBACD;oBACE,IAAI,EAAE,gBAAgB;oBACtB,WAAW,EAAE,CAAC,UAAU,EAAE,cAAc,CAAC;oBACzC,OAAO,EACL,mHAAmH;iBACtH;gBACD;oBACE,IAAI,EAAE,oBAAoB;oBAC1B,OAAO,EAAE,+EAA+E;iBACzF;gBACD;oBACE,IAAI,EAAE,2BAA2B;oBACjC,OAAO,EAAE,8DAA8D;iBACxE;gBACD;oBACE,IAAI,EAAE,6BAA6B;oBACnC,OAAO,EAAE,8DAA8D;iBACxE;gBACD;oBACE,IAAI,EAAE,0BAA0B;oBAChC,OAAO,EACL,0HAA0H;iBAC7H;aACF;YAED,QAAQ,EAAE;gBACR;oBACE,KAAK,EAAE,CAAC,WAAW,CAAC;oBACpB,OAAO,EAAE,sFAAsF;iBAChG;gBACD;oBACE,KAAK,EAAE,CAAC,cAAc,CAAC;oBACvB,OAAO,EAAE,sFAAsF;iBAChG;aACF;SACF;KACF;CACF,CAAC","sourcesContent":["import type { Linter } from \"eslint\";\n\nexport const restrictedImportRules: Linter.RulesRecord = {\n \"no-restricted-imports\": [\n \"error\",\n {\n paths: [\n {\n name: \"react-dom/test-utils\",\n message: \"Please use 'act' from the @testing-library/react instead.\",\n },\n {\n name: \"react-i18next\",\n importNames: [\"useTranslation\"],\n message: \"Please import useTranslation from @trackunit/i18n-manager-translation instead.\",\n },\n {\n name: \"react-i18next\",\n importNames: [\"Trans\"],\n message: \"Please import Trans from @trackunit/i18n-manager-translation instead.\",\n },\n {\n name: \"@apollo/client\",\n importNames: [\"useQuery\", \"useLazyQuery\"],\n message:\n \"Please import the same from @trackunit/react-graphql-hooks instead, to ensure loading state is handled correctly.\",\n },\n {\n name: \"@nx/plugin/testing\",\n message: \"Please import it from @trackunit/nx-utils instead or expose it from that lib.\",\n },\n {\n name: \"@heroicons/react/20/solid\",\n message: \"Please use the Icon component from react-components instead.\",\n },\n {\n name: \"@heroicons/react/24/outline\",\n message: \"Please use the Icon component from react-components instead.\",\n },\n {\n name: \"class-variance-authority\",\n message:\n \"Import our wrappers from, @trackunit/css-class-variance-utilities or twMerge instead. [cva -> cvaMerge], [cx -> twMerge]\",\n },\n ],\n\n patterns: [\n {\n group: [\"date-fns*\"],\n message: \"Please use @trackunit/date-and-time-utils or @trackunit/date-and-time-hooks instead.\",\n },\n {\n group: [\"date-fns-tz*\"],\n message: \"Please use @trackunit/date-and-time-utils or @trackunit/date-and-time-hooks instead.\",\n },\n ],\n },\n ],\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"testing-library.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/fragments/testing-library.ts"],"names":[],"mappings":";;;AACA,wCAA4C;AAE5C,MAAM,WAAW,GAAG,wBAAc,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;AAEhD,QAAA,wBAAwB,GAAuB,MAAM,CAAC,WAAW,CAC5E,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAuC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAC3G,CAAC","sourcesContent":["import type { Linter } from \"eslint\";\nimport { testingLibrary } from \"../plugins\";\n\nconst configRules = testingLibrary.configs.react.rules ?? {};\n\nexport const reactTestingLibraryRules: Linter.RulesRecord = Object.fromEntries(\n Object.entries(configRules).filter((entry): entry is [string, Linter.RuleEntry] => entry[1] !== undefined)\n);\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"typescript-rules.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/fragments/typescript-rules.ts"],"names":[],"mappings":";;;AAEa,QAAA,eAAe,GAAuB;IACjD,oCAAoC,EAAE,OAAO;IAC7C,wCAAwC,EAAE,OAAO;IACjD,uCAAuC,EAAE,OAAO;IAChD,6CAA6C,EAAE,OAAO;IACtD,gBAAgB,EAAE,KAAK;IACvB,mCAAmC,EAAE;QACnC,OAAO;QACP;YACE,IAAI,EAAE,KAAK;YACX,iBAAiB,EAAE,IAAI;YACvB,YAAY,EAAE,KAAK;YACnB,yBAAyB,EAAE,IAAI;YAC/B,8BAA8B,EAAE,IAAI;YACpC,iBAAiB,EAAE,IAAI;YACvB,kBAAkB,EAAE,IAAI;SACzB;KACF;IACD,+BAA+B,EAAE;QAC/B,OAAO;QACP;YACE,OAAO,EAAE,SAAS;SACnB;KACF;IACD,iCAAiC,EAAE,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;IACvE,8BAA8B,EAAE;QAC9B,OAAO;QACP;YACE,KAAK,EAAE,KAAK;SACb;KACF;IACD,+CAA+C,EAAE;QAC/C,MAAM;QACN;YACE,oBAAoB,EAAE,IAAI;YAC1B,mBAAmB,EAAE,IAAI;SAC1B;KACF;IACD,sCAAsC,EAAE;QACtC,OAAO;QACP;YACE,QAAQ,EAAE,WAAW;YACrB,MAAM,EAAE,CAAC,YAAY,CAAC;YAEtB,MAAM,EAAE;gBACN,KAAK,EAAE,SAAS;gBAChB,KAAK,EAAE,KAAK;aACb;SACF;QACD;YACE,QAAQ,EAAE,eAAe;YACzB,MAAM,EAAE,CAAC,YAAY,CAAC;YAEtB,MAAM,EAAE;gBACN,KAAK,EAAE,2BAA2B;gBAClC,KAAK,EAAE,IAAI;aACZ;SACF;KACF;IACD,0CAA0C,EAAE,MAAM;IAClD,sCAAsC,EAAE,OAAO;IAC/C,0CAA0C,EAAE,OAAO;IACnD,iCAAiC,EAAE,OAAO;IAC1C,mCAAmC,EAAE,MAAM;IAC3C,mCAAmC,EAAE,MAAM;IAC3C,oCAAoC,EAAE,OAAO;IAC7C,yCAAyC,EAAE,OAAO;IAClD,yCAAyC,EAAE,OAAO;IAClD,kDAAkD,EAAE;QAClD,OAAO;QACP;YACE,aAAa,EAAE,UAAU;YACzB,SAAS,EAAE;gBACT,SAAS,EAAE,UAAU;gBACrB,YAAY,EAAE,UAAU;gBACxB,mBAAmB,EAAE,UAAU;aAChC;SACF;KACF;IACD,kDAAkD,EAAE,OAAO;IAC3D,uCAAuC,EAAE,MAAM;IAC/C,wCAAwC,EAAE;QACxC,OAAO;QACP;YACE,KAAK,EAAE;gBACL,UAAU,EAAE;oBACV,OAAO,EAAE,6CAA6C;iBACvD;gBAED,EAAE,EAAE;oBACF,OAAO,EAAE,6CAA6C;iBACvD;aACF;SACF;KACF;CACF,CAAC","sourcesContent":["import type { Linter } from \"eslint\";\n\nexport const typescriptRules: Linter.RulesRecord = {\n \"@typescript-eslint/no-explicit-any\": \"error\",\n \"@typescript-eslint/no-inferrable-types\": \"error\",\n \"@typescript-eslint/unified-signatures\": \"error\",\n \"@typescript-eslint/no-unnecessary-condition\": \"error\",\n \"no-unused-vars\": \"off\",\n \"@typescript-eslint/no-unused-vars\": [\n \"error\",\n {\n args: \"all\",\n argsIgnorePattern: \"^_\",\n caughtErrors: \"all\",\n caughtErrorsIgnorePattern: \"^_\",\n destructuredArrayIgnorePattern: \"^_\",\n varsIgnorePattern: \"^_\",\n ignoreRestSiblings: true,\n },\n ],\n \"@typescript-eslint/array-type\": [\n \"error\",\n {\n default: \"generic\",\n },\n ],\n \"@typescript-eslint/no-redeclare\": [\"error\", { builtinGlobals: false }],\n \"@typescript-eslint/no-shadow\": [\n \"error\",\n {\n hoist: \"all\",\n },\n ],\n \"@typescript-eslint/strict-boolean-expressions\": [\n \"warn\",\n {\n allowNullableBoolean: true,\n allowNullableString: true,\n },\n ],\n \"@typescript-eslint/naming-convention\": [\n \"error\",\n {\n selector: \"interface\",\n format: [\"PascalCase\"],\n\n custom: {\n regex: \"^I[A-Z]\",\n match: false,\n },\n },\n {\n selector: \"typeParameter\",\n format: [\"PascalCase\"],\n\n custom: {\n regex: \"^(T|Keys?)[A-Z][a-zA-Z]+$\",\n match: true,\n },\n },\n ],\n \"@typescript-eslint/no-non-null-assertion\": \"warn\",\n \"@typescript-eslint/no-empty-function\": \"error\",\n \"@typescript-eslint/no-unused-expressions\": \"error\",\n \"@typescript-eslint/dot-notation\": \"error\",\n \"@typescript-eslint/await-thenable\": \"warn\",\n \"@typescript-eslint/ban-ts-comment\": \"warn\",\n \"@typescript-eslint/member-ordering\": \"error\",\n \"@typescript-eslint/no-empty-object-type\": \"error\",\n \"@typescript-eslint/no-floating-promises\": \"error\",\n \"@typescript-eslint/explicit-member-accessibility\": [\n \"error\",\n {\n accessibility: \"explicit\",\n overrides: {\n accessors: \"explicit\",\n constructors: \"explicit\",\n parameterProperties: \"explicit\",\n },\n },\n ],\n \"@typescript-eslint/no-unnecessary-type-assertion\": \"error\",\n \"@typescript-eslint/no-require-imports\": \"warn\",\n \"@typescript-eslint/no-restricted-types\": [\n \"error\",\n {\n types: {\n \"React.FC\": {\n message: \"Please use props interface or type instead.\",\n },\n\n FC: {\n message: \"Please use props interface or type instead.\",\n },\n },\n },\n ],\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/index.ts"],"names":[],"mappings":";;;AAAA,yCAAsC;AACtC,2CAA8C;AAEjC,QAAA,OAAO,GAAG;IACrB,IAAI,EAAJ,WAAI;IACJ,KAAK,EAAE,mBAAW;CACnB,CAAC","sourcesContent":["import { base } from \"./presets/base\";\nimport { reactPreset } from \"./presets/react\";\n\nexport const configs = {\n base,\n react: reactPreset,\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugins.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/plugins.ts"],"names":[],"mappings":";;;;AAAA;;;;;;;;GAQG;AACH,8DAAwC;AAwBtC,gBAAE;AAvBJ,2FAAqE;AA4BnE,4CAAgB;AA3BlB,4EAAsD;AA0BpD,4BAAQ;AAzBV,+EAA+D;AAc7D,+BAdK,cAAoB,CAcL;AAbtB,2EAAqD;AAenD,oCAAY;AAdd,iEAA2C;AAezC,oBAAI;AAdN,mEAA6C;AAe3C,sBAAK;AAdP,sEAAgD;AAgB9C,wBAAM;AAfR,mEAA6C;AAiB3C,sBAAK;AAhBP,8EAAwD;AAiBtD,gCAAU;AAhBZ,0GAA2D;AAiBzD,yBAjBK,uCAAc,CAiBL;AAhBhB,yDAAmC;AAOjC,0BAAO;AANT,yEAAmD;AAUjD,kCAAW;AATb,4CAAwC;AAE3B,QAAA,gBAAgB,GAAG,EAAE,KAAK,EAAE,oBAAQ,EAAE,CAAC","sourcesContent":["/**\n * Shared plugin instances for ESLint flat config.\n *\n * ESLint flat config requires that the same plugin name always maps to the same\n * object reference. With TypeScript's __importStar() helper (from esModuleInterop),\n * each file that does `import * as foo from \"pkg\"` gets its own wrapper object.\n * By importing all plugins once here and re-exporting, all presets share the same\n * object references.\n */\nimport * as nx from \"@nx/eslint-plugin\";\nimport * as typescriptEslint from \"@typescript-eslint/eslint-plugin\";\nimport * as tsParser from \"@typescript-eslint/parser\";\nimport eslintConfigPrettier from \"eslint-config-prettier/flat\";\nimport * as importPlugin from \"eslint-plugin-import\";\nimport * as jest from \"eslint-plugin-jest\";\nimport * as jsdoc from \"eslint-plugin-jsdoc\";\nimport * as noNull from \"eslint-plugin-no-null\";\nimport * as react from \"eslint-plugin-react\";\nimport * as reactHooks from \"eslint-plugin-react-hooks\";\nimport testingLibrary from \"eslint-plugin-testing-library\";\nimport * as globals from \"globals\";\nimport * as jsoncParser from \"jsonc-eslint-parser\";\nimport { rulesMap } from \"../rules-map\";\n\nexport const localRulesPlugin = { rules: rulesMap };\nexport {\n eslintConfigPrettier,\n globals,\n importPlugin,\n jest,\n jsdoc,\n jsoncParser,\n noNull,\n nx,\n react,\n reactHooks,\n testingLibrary,\n tsParser,\n typescriptEslint,\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/presets/base.ts"],"names":[],"mappings":";;;AAAA,4EAAuE;AAEvE,kDAAqD;AACrD,4DAAwD;AACxD,gEAAgE;AAChE,0DAA2D;AAC3D,sEAAqE;AACrE,oFAA6H;AAC7H,wEAAwE;AACxE,oEAAgE;AAChE,wCAUoB;AACpB,oCAA4C;AAE/B,QAAA,IAAI,GAAG;IAClB,uBAAa;IACb;QACE,OAAO,EAAE;YACP,KAAK,EAAE,YAAE;YACT,YAAY,EAAE,0BAAgB;YAC9B,oBAAoB,EAAE,0BAAgB;YACtC,SAAS,EAAE,gBAAM;YACjB,UAAU,EAAE,sBAAY;YACxB,KAAK,EAAL,eAAK;SACN;QAED,KAAK,EAAE;YACL,GAAG,uCAAmB;YACtB,GAAG,0CAAqB;SACzB;KACF;IACD,IAAA,iCAAc,EAAC;QACb,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE;QAC9B,OAAO,EAAE;YACP,UAAU,EAAE,sBAAY;SACzB;QACD,KAAK,EAAE;YACL,qCAAqC,EAAE;gBACrC,OAAO;gBACP;oBACE,UAAU,EAAE,IAAA,wBAAgB,GAAE;oBAC9B,eAAe,EAAE;wBACf,oBAAoB;wBACpB,oBAAoB;wBACpB,iBAAiB;wBACjB,YAAY;wBACZ,aAAa;wBACb,eAAe;wBACf,kBAAkB;wBAClB,kBAAkB;wBAClB,iBAAiB;wBACjB,mBAAmB;wBACnB,iBAAiB;wBACjB,iBAAiB;wBACjB,mBAAmB;wBACnB,0BAA0B;wBAC1B,uBAAuB;wBACvB,4BAA4B;wBAC5B,kBAAkB;wBAClB,eAAe;wBACf,aAAa;wBACb,6BAA6B;wBAC7B,oBAAoB;wBACpB,6CAA6C;wBAC7C,4BAA4B;qBAC7B;oBACD,oBAAoB,EAAE,KAAK;oBAC3B,gBAAgB,EAAE,IAAI;oBACtB,mBAAmB,EAAE,IAAI;iBAC1B;aACF;SACF;KACF,CAAC;IACF;QACE,KAAK,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,CAAC;QAErD,eAAe,EAAE;YACf,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,QAAQ;YACpB,MAAM,EAAE,kBAAQ;YAChB,aAAa,EAAE;gBACb,OAAO,EAAE,CAAC,oBAAoB,CAAC;aAChC;SACF;QACD,KAAK,EAAE;YACL,mBAAmB,EAAE,OAAO;YAC5B,KAAK,EAAE,OAAO;YACd,cAAc,EAAE,OAAO;YACvB,UAAU,EAAE,OAAO;YACnB,WAAW,EAAE,OAAO;YACpB,aAAa,EAAE,OAAO;YACtB,sBAAsB,EAAE,OAAO;YAC/B,UAAU,EAAE,OAAO;YACnB,SAAS,EAAE,OAAO;YAClB,YAAY,EAAE,OAAO;YACrB,QAAQ,EAAE,OAAO;YACjB,cAAc,EAAE,OAAO;YACvB,iBAAiB,EAAE,OAAO;YAC1B,6BAA6B,EAAE,OAAO;YACtC,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;YAC3B,eAAe,EAAE,OAAO;YACxB,iBAAiB,EAAE,KAAK;YACxB,iBAAiB,EAAE,KAAK;YACxB,sBAAsB,EAAE,KAAK;YAC7B,cAAc,EAAE,KAAK;YACrB,mBAAmB,EAAE,KAAK;YAC1B,uBAAuB,EAAE,KAAK;YAC9B,WAAW,EAAE,KAAK;YAElB,GAAG,6BAAe;YAElB,uBAAuB,EAAE,qDAA0B;YAEnD,qCAAqC,EAAE,OAAO;YAC9C,oCAAoC,EAAE,MAAM;YAC5C,uCAAuC,EAAE,OAAO;YAEhD,GAAG,0BAAW;YAEd,GAAG,kCAAe;SACnB;KACF;IACD;QACE,KAAK,EAAE,CAAC,iBAAiB,CAAC;QAC1B,eAAe,EAAE;YACf,MAAM,EAAE,qBAAW;SACpB;QACD,OAAO,EAAE;YACP,YAAY,EAAE,0BAAgB;SAC/B;QACD,KAAK,EAAE;YACL,4DAA4D,EAAE,OAAO;YACrE,yCAAyC,EAAE,MAAM;SAClD;KACF;IACD;QACE,KAAK,EAAE,CAAC,gCAAgC,CAAC;QACzC,eAAe,EAAE;YACf,MAAM,EAAE,qBAAW;SACpB;QACD,OAAO,EAAE;YACP,YAAY,EAAE,0BAAgB;SAC/B;QACD,KAAK,EAAE;YACL,sCAAsC,EAAE,OAAO;SAChD;KACF;IACD,mEAAwC;IACxC,kCAAiB;IACjB;QACE,KAAK,EAAE;YACL,sBAAsB;YACtB,yBAAyB;YACzB,qBAAqB;YACrB,qBAAqB;YACrB,sBAAsB;SACvB;QACD,KAAK,EAAE;YACL,uCAAuC,EAAE,KAAK;SAC/C;KACF;IACD;QACE,KAAK,EAAE,CAAC,sBAAsB,CAAC;QAC/B,KAAK,EAAE;YACL,+BAA+B,EAAE,KAAK;SACvC;KACF;IACD,8BAAoB;IACpB;QACE,KAAK,EAAE,CAAC,8BAA8B,EAAE,2BAA2B,CAAC;QACpE,KAAK,EAAE;YACL,+BAA+B,EAAE,KAAK;SACvC;KACF;CACF,CAAC","sourcesContent":["import { createSkipWhen } from \"../../config-helpers/create-skip-when\";\n\nimport { globalIgnores } from \"../fragments/ignores\";\nimport { importRules } from \"../fragments/import-rules\";\nimport { baseJestOverrides } from \"../fragments/jest-overrides\";\nimport { basicJsdocRules } from \"../fragments/jsdoc-rules\";\nimport { moduleBoundaryRules } from \"../fragments/module-boundaries\";\nimport { noDirectStorageGlobalsExceptionOverrides, noDirectStorageGlobalsRule } from \"../fragments/no-direct-storage-access\";\nimport { restrictedImportRules } from \"../fragments/restricted-imports\";\nimport { typescriptRules } from \"../fragments/typescript-rules\";\nimport {\n eslintConfigPrettier,\n importPlugin,\n jsdoc,\n jsoncParser,\n localRulesPlugin,\n noNull,\n nx,\n tsParser,\n typescriptEslint,\n} from \"../plugins\";\nimport { findMonorepoRoot } from \"../utils\";\n\nexport const base = [\n globalIgnores,\n {\n plugins: {\n \"@nx\": nx,\n \"@trackunit\": localRulesPlugin,\n \"@typescript-eslint\": typescriptEslint,\n \"no-null\": noNull,\n \"import-x\": importPlugin,\n jsdoc,\n },\n\n rules: {\n ...moduleBoundaryRules,\n ...restrictedImportRules,\n },\n },\n createSkipWhen({\n when: { tags: [\"scope:tool\"] },\n plugins: {\n \"import-x\": importPlugin,\n },\n rules: {\n \"import-x/no-extraneous-dependencies\": [\n \"error\",\n {\n packageDir: findMonorepoRoot(),\n devDependencies: [\n \"**/*.spec.{ts,tsx}\",\n \"**/*.test.{ts,tsx}\",\n \"**/jest.setup.*\",\n \"**/test/**\",\n \"**/tests/**\",\n \"**/testing/**\",\n \"**/test-setup/**\",\n \"**/test-utils/**\",\n \"**/vite.setup.*\",\n \"**/vite.config.ts\",\n \"**/__tests__/**\",\n \"**/__mocks__/**\",\n \"**/mocks.{ts,tsx}\",\n \"**/core-contexts-test/**\",\n \"**/*.stories.{ts,tsx}\",\n \"**/storybookUtils.{ts,tsx}\",\n \"**/.storybook/**\",\n \"**/scripts/**\",\n \"**/tools/**\",\n \"**/*.config.{ts,js,cjs,mjs}\",\n \"**/css/tailwind/**\",\n \"**/css/tailwind-custom-properties-plugin/**\",\n \"**/css/component-tokens/**\",\n ],\n optionalDependencies: false,\n peerDependencies: true,\n bundledDependencies: true,\n },\n ],\n },\n }),\n {\n files: [\"**/*.ts\", \"**/*.tsx\", \"**/*.js\", \"**/*.jsx\"],\n\n languageOptions: {\n ecmaVersion: 5,\n sourceType: \"script\",\n parser: tsParser,\n parserOptions: {\n project: [\"./tsconfig.*?.json\"],\n },\n },\n rules: {\n \"constructor-super\": \"error\",\n curly: \"error\",\n \"default-case\": \"error\",\n \"id-match\": \"error\",\n \"no-caller\": \"error\",\n \"no-debugger\": \"error\",\n \"no-duplicate-imports\": \"error\",\n \"no-empty\": \"error\",\n \"no-eval\": \"error\",\n \"no-console\": \"error\",\n \"no-var\": \"error\",\n \"prefer-const\": \"error\",\n \"prefer-template\": \"error\",\n \"no-template-curly-in-string\": \"error\",\n eqeqeq: [\"error\", \"always\"],\n \"no-undef-init\": \"error\",\n \"no-invalid-this\": \"off\",\n \"no-null/no-null\": \"off\",\n \"no-underscore-dangle\": \"off\",\n \"no-redeclare\": \"off\",\n \"no-empty-function\": \"off\",\n \"no-unused-expressions\": \"off\",\n \"no-shadow\": \"off\",\n\n ...basicJsdocRules,\n\n \"no-restricted-globals\": noDirectStorageGlobalsRule,\n\n \"@trackunit/no-internal-barrel-files\": \"error\",\n \"@trackunit/no-typescript-assertion\": \"warn\",\n \"@trackunit/no-dynamic-translation-key\": \"error\",\n\n ...importRules,\n\n ...typescriptRules,\n },\n },\n {\n files: [\"**/project.json\"],\n languageOptions: {\n parser: jsoncParser,\n },\n plugins: {\n \"@trackunit\": localRulesPlugin,\n },\n rules: {\n \"@trackunit/no-internal-graphql-when-tagged-with-gql-public\": \"error\",\n \"@trackunit/no-deprecated-graphql-fields\": \"warn\",\n },\n },\n {\n files: [\"**/locales/en/translation.json\"],\n languageOptions: {\n parser: jsoncParser,\n },\n plugins: {\n \"@trackunit\": localRulesPlugin,\n },\n rules: {\n \"@trackunit/no-unused-translation-key\": \"error\",\n },\n },\n noDirectStorageGlobalsExceptionOverrides,\n baseJestOverrides,\n {\n files: [\n \"**/eslint.config.cjs\",\n \"**/iris-app-manifest.ts\",\n \"**/rspack.config.ts\",\n \"**/rspack.config.js\",\n \"**/webpack.config.ts\",\n ],\n rules: {\n \"@typescript-eslint/no-require-imports\": \"off\",\n },\n },\n {\n files: [\"**/eslint.config.cjs\"],\n rules: {\n \"@nx/enforce-module-boundaries\": \"off\",\n },\n },\n eslintConfigPrettier,\n {\n files: [\"**/*.stories.{ts,tsx,js,jsx}\", \"**/*.demo.{ts,tsx,js,jsx}\"],\n rules: {\n \"@nx/enforce-module-boundaries\": \"off\",\n },\n },\n];\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"e2e.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/presets/e2e.ts"],"names":[],"mappings":";;;AAAa,QAAA,GAAG,GAAG;IACjB;QACE,KAAK,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,CAAC;QAErD,eAAe,EAAE;YACf,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,QAAQ;YAEpB,aAAa,EAAE;gBACb,OAAO,EAAE,CAAC,oBAAoB,EAAE,iBAAiB,EAAE,4BAA4B,CAAC;aACjF;SACF;KACF;IACD;QACE,KAAK,EAAE,CAAC,oBAAoB,EAAE,qBAAqB,CAAC;QACpD,KAAK,EAAE;YACL,uCAAuC,EAAE,KAAK;YAC9C,gCAAgC,EAAE,KAAK;YACvC,8BAA8B,EAAE,KAAK;YACrC,iDAAiD,EAAE,KAAK;YACxD,wCAAwC,EAAE,KAAK;SAChD;KACF;CACF,CAAC","sourcesContent":["export const e2e = [\n {\n files: [\"**/*.ts\", \"**/*.tsx\", \"**/*.js\", \"**/*.jsx\"],\n\n languageOptions: {\n ecmaVersion: 5,\n sourceType: \"script\",\n\n parserOptions: {\n project: [\"./tsconfig.*?.json\", \"./tsconfig.json\", \"./playwright/tsconfig.json\"],\n },\n },\n },\n {\n files: [\"playwright/**/*.ts\", \"playwright/**/*.tsx\"],\n rules: {\n \"testing-library/prefer-screen-queries\": \"off\",\n \"testing-library/no-node-access\": \"off\",\n \"testing-library/no-container\": \"off\",\n \"testing-library/render-result-naming-convention\": \"off\",\n \"testing-library/no-render-in-lifecycle\": \"off\",\n },\n },\n];\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"react.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/presets/react.ts"],"names":[],"mappings":";;;AAAA,oFAG+C;AAC/C,0DAAwE;AACxE,kEAAwE;AACxE,wCAWoB;AAEP,QAAA,WAAW,GAAG;IACzB;QACE,OAAO,EAAE;YACP,YAAY,EAAE,0BAAgB;YAC9B,oBAAoB,EAAE,0BAAgB;YACtC,KAAK,EAAL,eAAK;YACL,KAAK,EAAL,eAAK;YACL,aAAa,EAAE,oBAAU;YACzB,iBAAiB,EAAE,wBAAc;YACjC,KAAK,EAAE,YAAE;SACV;QAED,QAAQ,EAAE;YACR,KAAK,EAAE;gBACL,OAAO,EAAE,QAAQ;aAClB;SACF;QACD,eAAe,EAAE;YACf,OAAO,EAAE;gBACP,GAAG,iBAAO,CAAC,OAAO;gBAClB,GAAG,cAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO;gBACpC,GAAG,iBAAO,CAAC,IAAI;gBACf,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,UAAU;aACnB;YACD,MAAM,EAAE,kBAAQ;YAChB,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,UAAU;YACtB,aAAa,EAAE;gBACb,YAAY,EAAE;oBACZ,GAAG,EAAE,IAAI;iBACV;aACF;SACF;KACF;IACD;QACE,KAAK,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,CAAC;QACrD,KAAK,EAAE;YACL,GAAG,8BAAgB;YAEnB,yBAAyB,EAAE;gBACzB,OAAO;gBACP;oBACE,GAAG,EAAE,CAAC;iBACP;aACF;YAED,gBAAgB,EAAE,OAAO;YACzB,eAAe,EAAE,OAAO;YAExB,GAAG,wBAAU;YAEb,sBAAsB,EAAE;gBACtB,MAAM;gBACN;oBACE,QAAQ,EAAE,mBAAmB;oBAC7B,OAAO,EAAE,8DAA8D;iBACxE;aACF;YAED,0BAA0B,EAAE,wDAA6B;SAC1D;KACF;IACD,oEAAyC;IACzC;QACE,KAAK,EAAE,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;QAC9C,KAAK,EAAE;YACL,qBAAqB,EAAE,KAAK;YAC5B,YAAY,EAAE,KAAK;YACnB,sCAAsC,EAAE,KAAK;YAC7C,mCAAmC,EAAE,KAAK;YAC1C,4CAA4C,EAAE,KAAK;YAEnD,2EAA2E;YAC3E,kFAAkF;YAClF,kDAAkD,EAAE,OAAO;SAC5D;KACF;IACD;QACE,KAAK,EAAE,CAAC,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;QACzE,KAAK,EAAE;YACL,mCAAmC,EAAE,KAAK;YAC1C,4CAA4C,EAAE,KAAK;YACnD,0BAA0B,EAAE,KAAK;SAClC;KACF;IACD;QACE,KAAK,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;QAExC,OAAO,EAAE;YACP,IAAI,EAAJ,cAAI;YACJ,iBAAiB,EAAE,wBAAc;SAClC;QACD,eAAe,EAAE;YACf,OAAO,EAAE;gBACP,GAAG,iBAAO,CAAC,OAAO;gBAClB,GAAG,cAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO;gBACpC,GAAG,iBAAO,CAAC,IAAI;gBACf,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,UAAU;aACnB;YAED,MAAM,EAAE,kBAAQ;SACjB;QAED,KAAK,EAAE;YACL,GAAG,cAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK;YACjC,GAAG,cAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK;YAC3B,GAAG,0CAAwB;YAC3B,6BAA6B,EAAE,OAAO;YACtC,oBAAoB,EAAE,OAAO;SAC9B;KACF;CACF,CAAC","sourcesContent":["import {\n noDirectStoragePropertiesRule,\n noDirectStoragePropertyExceptionOverrides,\n} from \"../fragments/no-direct-storage-access\";\nimport { reactCustomRules, reactRules } from \"../fragments/react-rules\";\nimport { reactTestingLibraryRules } from \"../fragments/testing-library\";\nimport {\n globals,\n jest,\n jsdoc,\n localRulesPlugin,\n nx,\n react,\n reactHooks,\n testingLibrary,\n tsParser,\n typescriptEslint,\n} from \"../plugins\";\n\nexport const reactPreset = [\n {\n plugins: {\n \"@trackunit\": localRulesPlugin,\n \"@typescript-eslint\": typescriptEslint,\n jsdoc,\n react,\n \"react-hooks\": reactHooks,\n \"testing-library\": testingLibrary,\n \"@nx\": nx,\n },\n\n settings: {\n react: {\n version: \"detect\",\n },\n },\n languageOptions: {\n globals: {\n ...globals.browser,\n ...jest.environments.globals.globals,\n ...globals.node,\n Text: \"writable\",\n screen: \"writable\",\n },\n parser: tsParser,\n ecmaVersion: 2022,\n sourceType: \"commonjs\",\n parserOptions: {\n ecmaFeatures: {\n jsx: true,\n },\n },\n },\n },\n {\n files: [\"**/*.ts\", \"**/*.tsx\", \"**/*.js\", \"**/*.jsx\"],\n rules: {\n ...reactCustomRules,\n\n \"no-multiple-empty-lines\": [\n \"error\",\n {\n max: 1,\n },\n ],\n\n \"no-unreachable\": \"error\",\n \"prefer-spread\": \"error\",\n\n ...reactRules,\n\n \"no-restricted-syntax\": [\n \"warn\",\n {\n selector: \"TSEnumDeclaration\",\n message: \"Please use string literal union or objects instead of enums.\",\n },\n ],\n\n \"no-restricted-properties\": noDirectStoragePropertiesRule,\n },\n },\n noDirectStoragePropertyExceptionOverrides,\n {\n files: [\"**/*.stories.ts\", \"**/*.stories.tsx\"],\n rules: {\n \"jsdoc/require-jsdoc\": \"off\",\n \"no-console\": \"off\",\n \"@typescript-eslint/no-empty-function\": \"off\",\n \"@trackunit/one-component-per-file\": \"off\",\n \"@trackunit/component-name-matches-filename\": \"off\",\n\n // Every Storybook folder implied by a story title must have a landing page\n // (*.docs.mdx with a matching <Meta title>). See docs/STORYBOOK-LANDING-PAGES.md.\n \"@trackunit/require-storybook-folder-landing-page\": \"error\",\n },\n },\n {\n files: [\"**/*.spec.ts\", \"**/*.spec.tsx\", \"**/*.test.ts\", \"**/*.test.tsx\"],\n rules: {\n \"@trackunit/one-component-per-file\": \"off\",\n \"@trackunit/component-name-matches-filename\": \"off\",\n \"no-restricted-properties\": \"off\",\n },\n },\n {\n files: [\"**/*.spec.ts\", \"**/*.spec.tsx\"],\n\n plugins: {\n jest,\n \"testing-library\": testingLibrary,\n },\n languageOptions: {\n globals: {\n ...globals.browser,\n ...jest.environments.globals.globals,\n ...globals.node,\n Text: \"writable\",\n screen: \"writable\",\n },\n\n parser: tsParser,\n },\n\n rules: {\n ...jest.configs.recommended.rules,\n ...jest.configs.style.rules,\n ...reactTestingLibraryRules,\n \"jest/no-commented-out-tests\": \"error\",\n \"jest/expect-expect\": \"error\",\n },\n },\n];\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/presets/server.ts"],"names":[],"mappings":";;;;AAAA,2CAAkD;AAClD,gFAA0D;AAE1D,wCAAsD;AAEzC,QAAA,MAAM,GAAG;IACpB;QACE,eAAe,EAAE;YACf,OAAO,EAAE;gBACP,GAAG,iBAAO,CAAC,OAAO;aACnB;YAED,MAAM,EAAE,kBAAQ;SACjB;KACF;IACD;QACE,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;QAC7B,OAAO,EAAE;YACP,KAAK,EAAL,eAAK;YACL,cAAc,EAAE,IAAA,yBAAgB,EAAC,WAAW,CAAC;SAC9C;QACD,eAAe,EAAE;YACf,aAAa,EAAE;gBACb,OAAO,EAAE,CAAC,oBAAoB,CAAC;aAChC;SACF;QAED,KAAK,EAAE;YACL,GAAG,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK;YACxC,qCAAqC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC;YACvD,2CAA2C,EAAE,KAAK;YAClD,wCAAwC,EAAE,OAAO;YACjD,0CAA0C,EAAE,KAAK;SAClD;KACF;CACF,CAAC","sourcesContent":["import { fixupPluginRules } from \"@eslint/compat\";\nimport * as typeGraphql from \"eslint-plugin-type-graphql\";\n\nimport { globals, jsdoc, tsParser } from \"../plugins\";\n\nexport const server = [\n {\n languageOptions: {\n globals: {\n ...globals.browser,\n },\n\n parser: tsParser,\n },\n },\n {\n files: [\"**/*.ts\", \"**/*.js\"],\n plugins: {\n jsdoc,\n \"type-graphql\": fixupPluginRules(typeGraphql),\n },\n languageOptions: {\n parserOptions: {\n project: [\"./tsconfig.*?.json\"],\n },\n },\n\n rules: {\n ...typeGraphql.configs.recommended.rules,\n \"type-graphql/missing-decorator-type\": [\"error\", \"all\"],\n \"type-graphql/invalid-nullable-output-type\": \"off\",\n \"type-graphql/wrong-decorator-signature\": \"error\",\n \"type-graphql/invalid-nullable-input-type\": \"off\",\n },\n },\n];\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/config/utils.ts"],"names":[],"mappings":";;AAUA,4CAcC;;AAxBD,+CAAyB;AACzB,mDAA6B;AAE7B,IAAI,UAA8B,CAAC;AAEnC;;;;GAIG;AACH,SAAgB,gBAAgB;IAC9B,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,GAAG,GAAG,SAAS,CAAC;IACpB,OAAO,GAAG,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;YAC7C,UAAU,GAAG,GAAG,CAAC;YACjB,OAAO,GAAG,CAAC;QACb,CAAC;QACD,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC3B,OAAO,UAAU,CAAC;AACpB,CAAC","sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\n\nlet cachedRoot: string | undefined;\n\n/**\n * Finds the monorepo root by walking up from the config package directory\n * until a directory containing nx.json is found.\n * Falls back to process.cwd() if no nx.json is found.\n */\nexport function findMonorepoRoot(): string {\n if (cachedRoot !== undefined) {\n return cachedRoot;\n }\n let dir = __dirname;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, \"nx.json\"))) {\n cachedRoot = dir;\n return dir;\n }\n dir = path.dirname(dir);\n }\n cachedRoot = process.cwd();\n return cachedRoot;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-skip-when.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/config-helpers/create-skip-when.ts"],"names":[],"mappings":";;;AAqBA,gDAAmG;AAUnG,IAAI,eAAe,GAAG,CAAC,CAAC;AAExB;;GAEG;AACI,MAAM,cAAc,GAAG,CAAC,OAA8B,EAAqB,EAAE;IAClF,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAEzC,8CAA8C;IAC9C,MAAM,UAAU,GAAG,aAAa,eAAe,EAAE,EAAE,CAAC;IAEpD,4CAA4C;IAC5C,MAAM,YAAY,GAAoC,EAAE,CAAC;IAEzD,KAAK,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnE,KAAK,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACpE,MAAM,YAAY,GAAG,GAAG,kBAAkB,IAAI,QAAQ,EAAE,CAAC;YAEzD,sCAAsC;YACtC,YAAY,CAAC,YAAY,CAAC,GAAG;gBAC3B,IAAI,EAAE,YAAY,CAAC,IAAI;gBACvB,MAAM,CAAC,OAAyB;oBAC9B,gEAAgE;oBAChE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;oBAC3D,MAAM,QAAQ,GAAG,IAAA,6BAAkB,EAAC,QAAQ,CAAC,CAAC;oBAE9C,6CAA6C;oBAC7C,IAAI,QAAQ,IAAI,IAAA,iCAAsB,EAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC;wBACvD,0CAA0C;wBAC1C,OAAO,EAAE,CAAC;oBACZ,CAAC;oBAED,2CAA2C;oBAC3C,OAAO,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACtC,CAAC;aACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,MAAM,WAAW,GAAuB,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3D,4BAA4B;QAC5B,WAAW,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC;QAE9B,6BAA6B;QAC7B,WAAW,CAAC,GAAG,UAAU,IAAI,QAAQ,EAAE,CAAC,GAAG,UAAU,CAAC;IACxD,CAAC;IAED,OAAO;QACL,OAAO,EAAE;YACP,CAAC,UAAU,CAAC,EAAE;gBACZ,KAAK,EAAE,YAAY;aACpB;SACF;QACD,KAAK,EAAE,WAAW;KACnB,CAAC;AACJ,CAAC,CAAC;AArDW,QAAA,cAAc,kBAqDzB","sourcesContent":["/**\n * Helper to create ESLint config that wraps rules with skip-when-lib-has-tag-tool logic.\n *\n * This provides a cleaner API than manually using the skip-when-lib-has-tag-tool/ prefix.\n *\n * @example\n * createSkipWhen({\n * when: { tags: ['scope:tool'] },\n * plugins: {\n * 'import-x': importXPlugin,\n * },\n * rules: {\n * 'import-x/no-extraneous-dependencies': [\"error\", { ... }],\n * }\n * })\n *\n * Returns a config object with:\n * - A unique plugin containing the wrapped rules for this specific config\n * - Rules configured to use the wrapped versions\n */\nimport type { Linter, Rule } from \"eslint\";\nimport { getProjectMetadata, projectMatchesCriteria, type MatchCriteria } from \"../utils/nx-utils\";\n\ntype PluginMap = Record<string, { rules: Record<string, Rule.RuleModule> }>;\n\ntype CreateSkipWhenOptions = {\n when: MatchCriteria;\n plugins: PluginMap;\n rules: Linter.RulesRecord;\n};\n\nlet skipWhenCounter = 0;\n\n/**\n * Creates an ESLint config that wraps rules to skip enforcement based on NX project criteria.\n */\nexport const createSkipWhen = (options: CreateSkipWhenOptions): Linter.FlatConfig => {\n const { when, plugins, rules } = options;\n\n // Create a unique plugin name for this config\n const pluginName = `skip-when-${skipWhenCounter++}`;\n\n // Build wrapped rules from provided plugins\n const wrappedRules: Record<string, Rule.RuleModule> = {};\n\n for (const [originalPluginName, plugin] of Object.entries(plugins)) {\n for (const [ruleName, originalRule] of Object.entries(plugin.rules)) {\n const fullRuleName = `${originalPluginName}/${ruleName}`;\n\n // Create wrapped version of this rule\n wrappedRules[fullRuleName] = {\n meta: originalRule.meta,\n create(context: Rule.RuleContext) {\n // Check if this file belongs to a project matching the criteria\n const filename = context.filename || context.getFilename();\n const metadata = getProjectMetadata(filename);\n\n // Check if project matches the skip criteria\n if (metadata && projectMatchesCriteria(metadata, when)) {\n // Skip enforcement - return empty visitor\n return {};\n }\n\n // Otherwise, delegate to the original rule\n return originalRule.create(context);\n },\n };\n }\n }\n\n // Build the rules config\n const rulesConfig: Linter.RulesRecord = {};\n\n for (const [ruleName, ruleConfig] of Object.entries(rules)) {\n // Disable the original rule\n rulesConfig[ruleName] = \"off\";\n\n // Enable our wrapped version\n rulesConfig[`${pluginName}/${ruleName}`] = ruleConfig;\n }\n\n return {\n plugins: {\n [pluginName]: {\n rules: wrappedRules,\n },\n },\n rules: rulesConfig,\n };\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"component-name-matches-filename.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/component-name-matches-filename/component-name-matches-filename.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ESLint rule: component-name-matches-filename\n *\n * Enforces that every exported React component is named after the file it lives in.\n * For a file named `Foo.tsx`, the exported component must be named `Foo`.\n *\n * Anonymous default exports are skipped (no name to compare).\n * `index.*` files are skipped (they are entry-point re-export files, not component files).\n *\n * When combined with `one-component-per-file`, these two rules together fully enforce\n * the \"one named component per file\" convention.\n *\n * @example\n * // File: Foo.tsx\n * // Bad — exported name doesn't match filename\n * export function Bar() { return <div />; }\n *\n * // Good\n * export function Foo() { return <div />; }\n */\n\nimport { ESLintUtils } from \"@typescript-eslint/utils\";\nimport { minimatch } from \"minimatch\";\nimport path from \"path\";\nimport { createComponentFileTracker } from \"../../utils/component-utils\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}/${name}.ts`\n);\n\ntype MessageIds = \"componentNameMismatch\";\n\ntype AllowedMismatch = {\n /** Basename of the file (without extension) where the mismatch is permitted. Supports glob patterns (`*`, `?`). */\n file: string;\n /** Exported component name that is permitted despite not matching the filename. Supports glob patterns (`*`, `?`). */\n component: string;\n};\n\ntype Options = [{ allowedMismatches?: ReadonlyArray<AllowedMismatch> }];\n\nexport const componentNameMatchesFilename = createRule<Options, MessageIds>({\n name: \"component-name-matches-filename\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Enforce that exported React component names match the filename they live in. \" +\n \"index.* files and anonymous default exports are exempt.\",\n },\n messages: {\n componentNameMismatch:\n \"Component '{{name}}' should match the filename. \" + \"Rename it to '{{expected}}' or move it to its own file.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n allowedMismatches: {\n type: \"array\",\n description:\n \"Pairs that are exempt from the name-matching rule. Both `file` and `component` support glob patterns \" +\n \"(`*`, `?`), so one entry can cover a whole family of files (e.g. { file: '*Context', component: '*Provider' }).\",\n items: {\n type: \"object\",\n properties: {\n file: {\n type: \"string\",\n description:\n \"Basename of the file without extension. Supports glob patterns (`*`, `?`). \" +\n \"e.g. 'translation' or '*Context'.\",\n },\n component: {\n type: \"string\",\n description:\n \"Exported component name. Supports glob patterns (`*`, `?`). \" + \"e.g. 'Trans' or '*Provider'.\",\n },\n },\n required: [\"file\", \"component\"],\n additionalProperties: false,\n },\n },\n },\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [{}],\n create(context, [{ allowedMismatches = [] }]) {\n const filename = context.filename;\n const basename = path.basename(filename, path.extname(filename));\n\n if (basename === \"index\" || basename === \"<input>\") return {};\n\n // Normalize kebab-case and snake_case filenames to PascalCase.\n // e.g. `current-weather-status` → `CurrentWeatherStatus`, `app` → `App`.\n const expectedName = basename\n .split(/[-_]/)\n .map(segment => segment.charAt(0).toUpperCase() + segment.slice(1))\n .join(\"\");\n\n const tracker = createComponentFileTracker();\n\n return {\n FunctionDeclaration: tracker.onFunctionDeclaration,\n VariableDeclarator: tracker.onVariableDeclarator,\n ExportNamedDeclaration: tracker.onExportNamedDeclaration,\n ExportDefaultDeclaration: tracker.onExportDefaultDeclaration,\n\n \"Program:exit\"() {\n for (const { name, node } of tracker.getExportedComponents()) {\n if (name === null) continue; // anonymous default exports are exempt\n if (name === expectedName) continue;\n\n const isAllowed = allowedMismatches.some(\n entry => minimatch(basename, entry.file) && minimatch(name, entry.component)\n );\n if (isAllowed) continue;\n\n context.report({\n node,\n messageId: \"componentNameMismatch\",\n data: { name, expected: expectedName },\n });\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"cva-merge-base-classes-as-array.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array.ts"],"names":[],"mappings":";;;AAAA,wEAMwC;AACxC,oDAAiF;AAEjF,MAAM,UAAU,GAAG,mBAAW,CAAC,WAAW,CACxC,IAAI,CAAC,EAAE,CAAC,6FAA6F,IAAI,KAAK,CAC/G,CAAC;AAKF,MAAM,qBAAqB,GAAG,CAAC,OAAyB,EAAW,EAAE;IACnE,IAAI,OAAO,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QACrC,OAAO,OAAO,CAAC,YAAY,KAAK,UAAU,IAAI,OAAO,CAAC,aAAa,KAAK,CAAC,CAAC;IAC5E,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,KAAK,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QACvF,OAAO,OAAO,CAAC,aAAa,CAAC,YAAY,KAAK,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,aAAa,KAAK,CAAC,CAAC;IACxG,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CACxB,QAA2B,EACoC,EAAE;IACjE,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,sBAAc,CAAC,OAAO,IAAI,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC;AACxG,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACU,QAAA,0BAA0B,GAAG,UAAU,CAAsB;IACxE,IAAI,EAAE,iCAAiC;IACvC,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE;YACJ,WAAW,EAAE,wEAAwE;SACtF;QACD,OAAO,EAAE,MAAM;QACf,QAAQ,EAAE;YACR,gBAAgB,EAAE,4FAA4F;YAC9G,eAAe,EAAE,sDAAsD;SACxE;QACD,MAAM,EAAE,EAAE;KACX;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,cAAc,CAAC,IAA6B;gBAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;gBACnC,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,OAAO;gBACT,CAAC;gBAED,MAAM,kBAAkB,GAAG,IAAA,gDAA0B,EAAC,IAAI,CAAC;qBACxD,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,qBAAqB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;qBAC3D,MAAM,CAAC,iBAAiB,CAAC,CAAC;gBAE7B,mDAAmD;gBACnD,IAAI,QAAQ,CAAC,IAAI,KAAK,sBAAc,CAAC,OAAO,EAAE,CAAC;oBAC7C,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;oBAChD,IAAI,CAAC,iBAAiB,EAAE,CAAC;wBACvB,OAAO;oBACT,CAAC;oBAED,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC;oBACtC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;wBACxB,OAAO,CAAC,MAAM,CAAC;4BACb,IAAI;4BACJ,SAAS,EAAE,kBAAkB;4BAC7B,GAAG,CAAC,KAAK;gCACP,OAAO,KAAK,CAAC,WAAW,CAAC,iBAAiB,CAAC,OAAO,EAAE,IAAA,mCAAa,EAAC,IAAA,kCAAY,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC;4BAC1F,CAAC;yBACF,CAAC,CAAC;oBACL,CAAC;oBACD,OAAO;gBACT,CAAC;gBAED,sDAAsD;gBACtD,IAAI,QAAQ,CAAC,IAAI,KAAK,sBAAc,CAAC,eAAe,EAAE,CAAC;oBACrD,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;oBAE/F,IAAI,oBAAoB,EAAE,CAAC;wBACzB,OAAO,CAAC,MAAM,CAAC;4BACb,IAAI;4BACJ,SAAS,EAAE,iBAAiB;4BAC5B,GAAG,CAAC,KAAK;gCACP,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAA,kCAAY,EAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;gCACxF,OAAO,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAA,mCAAa,EAAC,UAAU,CAAC,CAAC,CAAC;4BAChE,CAAC;yBACF,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["import {\n type ClassnameContext,\n type ClassnameLocation,\n findClassnameStringsInCall,\n formatAsArray,\n splitClasses,\n} from \"@trackunit/css-classname-utils\";\nimport { AST_NODE_TYPES, ESLintUtils, 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 MessageIds = \"stringNeedsArray\" | \"arrayNeedsSplit\";\ntype Options = [];\n\nconst isCvaMergeBaseContext = (context: ClassnameContext): boolean => {\n if (context.type === \"function-call\") {\n return context.functionName === \"cvaMerge\" && context.argumentIndex === 0;\n }\n\n if (context.type === \"array-element\" && context.parentContext.type === \"function-call\") {\n return context.parentContext.functionName === \"cvaMerge\" && context.parentContext.argumentIndex === 0;\n }\n\n return false;\n};\n\nconst isLiteralLocation = (\n location: ClassnameLocation\n): location is ClassnameLocation & { fixNode: TSESTree.Literal } => {\n return location.fixNode.type === AST_NODE_TYPES.Literal && typeof location.fixNode.value === \"string\";\n};\n\n/**\n * ESLint rule that converts cvaMerge base styles to arrays if more than one class is used.\n *\n * @example\n * Invalid:\n * const cvaMyComponent = cvaMerge(\"text-danger-600 mb-4 font-semibold\");\n * const cvaMyComponent = cvaMerge([\"text-danger-600 mb-4\",\"font-semibold\"]);\n * Valid:\n * const cvaMyComponent = cvaMerge([\"text-danger-600\", \"mb-4\", \"font-semibold\"]);\n */\nexport const cvaMergeBaseClassesAsArray = createRule<Options, MessageIds>({\n name: \"cva-merge-base-classes-as-array\",\n meta: {\n type: \"layout\",\n docs: {\n description: \"Convert cvaMerge base styles to arrays if more than one class is used.\",\n },\n fixable: \"code\",\n messages: {\n stringNeedsArray: \"[cvaMerge] The first argument of cvaMerge should be an array if multiple classes are used.\",\n arrayNeedsSplit: \"[cvaMerge] Only one class per array item is allowed.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node: TSESTree.CallExpression) {\n const firstArg = node.arguments[0];\n if (!firstArg) {\n return;\n }\n\n const baseClassLocations = findClassnameStringsInCall(node)\n .filter(location => isCvaMergeBaseContext(location.context))\n .filter(isLiteralLocation);\n\n // Handle string literal: cvaMerge(\"class1 class2\")\n if (firstArg.type === AST_NODE_TYPES.Literal) {\n const baseClassLocation = baseClassLocations[0];\n if (!baseClassLocation) {\n return;\n }\n\n const value = baseClassLocation.value;\n if (value.includes(\" \")) {\n context.report({\n node,\n messageId: \"stringNeedsArray\",\n fix(fixer) {\n return fixer.replaceText(baseClassLocation.fixNode, formatAsArray(splitClasses(value)));\n },\n });\n }\n return;\n }\n\n // Handle array: cvaMerge([\"class1 class2\", \"class3\"])\n if (firstArg.type === AST_NODE_TYPES.ArrayExpression) {\n const hasMultiClassElement = baseClassLocations.some(location => location.value.includes(\" \"));\n\n if (hasMultiClassElement) {\n context.report({\n node,\n messageId: \"arrayNeedsSplit\",\n fix(fixer) {\n const allClasses = baseClassLocations.flatMap(location => splitClasses(location.value));\n return fixer.replaceText(firstArg, formatAsArray(allClasses));\n },\n });\n }\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"design-guideline-button-icon-size-match.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match.ts"],"names":[],"mappings":"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","sourcesContent":["import { ESLintUtils, type TSESLint, type TSESTree } from \"@typescript-eslint/utils\";\nimport * as ts from \"typescript\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/docs/rules/${name}.md`\n);\n\n// Helper to get possible string literal values from a variable's type\nfunction getPossibleStringLiterals(\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n identifier: TSESTree.Identifier\n): Array<string> | null {\n try {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n const tsNode = services.esTreeNodeToTSNodeMap.get(identifier);\n const type = checker.getTypeAtLocation(tsNode);\n\n const literalValues: Array<string> = [];\n\n // Type guard for string literal types\n const isStringLiteralType = (t: ts.Type): t is ts.Type & { value: string } => {\n if ((t.flags & ts.TypeFlags.StringLiteral) === 0) {\n return false;\n }\n // Check if the type has a value property and it's a string\n // eslint-disable-next-line @trackunit/no-typescript-assertion\n const typeWithValue = t as { value?: unknown };\n return \"value\" in typeWithValue && typeof typeWithValue.value === \"string\";\n };\n\n if (type.isUnion()) {\n for (const unionType of type.types) {\n if (isStringLiteralType(unionType)) {\n literalValues.push(unionType.value);\n }\n }\n } else if (isStringLiteralType(type)) {\n literalValues.push(type.value);\n }\n\n return literalValues.length > 0 ? literalValues : null;\n } catch {\n return null;\n }\n}\n\n// Helper to check if a conditional expression matches the expected button-icon size pattern\nfunction isCorrectConditionalExpression(expression: TSESTree.Expression, buttonVariableName: string): boolean {\n if (expression.type !== \"ConditionalExpression\") {\n return false;\n }\n\n const { test, consequent, alternate } = expression;\n\n // Check if test is: variable === \"large\"\n if (\n test.type === \"BinaryExpression\" &&\n test.operator === \"===\" &&\n test.left.type === \"Identifier\" &&\n test.left.name === buttonVariableName &&\n test.right.type === \"Literal\" &&\n test.right.value === \"large\"\n ) {\n // Check if consequent is \"medium\" and alternate is \"small\"\n return (\n consequent.type === \"Literal\" &&\n consequent.value === \"medium\" &&\n alternate.type === \"Literal\" &&\n alternate.value === \"small\"\n );\n }\n\n return false;\n}\n\nexport const designGuidelineButtonIconSizeMatch = createRule({\n name: \"design-guideline-button-icon-size-match\",\n meta: {\n type: \"suggestion\",\n docs: {\n description: \"Ensure Icon components within Button have the correct size prop based on the Button's size.\",\n },\n fixable: \"code\",\n schema: [],\n messages: {\n incorrectIconSize:\n \"Expected Icon size to be '{{expectedSize}}' for Button size '{{buttonSize}}', found '{{iconSize}}'.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n JSXOpeningElement(node: TSESTree.JSXOpeningElement) {\n if (node.name.type === \"JSXIdentifier\" && node.name.name === \"Button\") {\n const sizeAttr = node.attributes.find(\n (attr): attr is TSESTree.JSXAttribute =>\n attr.type === \"JSXAttribute\" && attr.name.type === \"JSXIdentifier\" && attr.name.name === \"size\"\n );\n\n const buttonSizeInfo = (() => {\n if (!sizeAttr?.value) return { type: \"implicit\", value: null };\n\n if (sizeAttr.value.type === \"Literal\" && typeof sizeAttr.value.value === \"string\") {\n return { type: \"literal\", value: sizeAttr.value.value };\n }\n\n if (sizeAttr.value.type === \"JSXExpressionContainer\") {\n const expr = sizeAttr.value.expression;\n if (expr.type === \"Identifier\") {\n return { type: \"variable\", value: expr.name, expression: expr };\n }\n return { type: \"expression\", value: null, expression: expr };\n }\n\n return { type: \"implicit\", value: null };\n })();\n\n node.attributes.forEach(attr => {\n if (\n attr.type === \"JSXAttribute\" &&\n attr.name.type === \"JSXIdentifier\" &&\n (attr.name.name === \"prefix\" || attr.name.name === \"suffix\") &&\n attr.value?.type === \"JSXExpressionContainer\"\n ) {\n // Find Icon element - could be direct or inside conditional\n const findIconElement = (expression: TSESTree.Expression): TSESTree.JSXOpeningElement | null => {\n if (\n expression.type === \"JSXElement\" &&\n expression.openingElement.name.type === \"JSXIdentifier\" &&\n expression.openingElement.name.name === \"Icon\"\n ) {\n return expression.openingElement;\n }\n\n if (expression.type === \"ConditionalExpression\") {\n // Check both consequent and alternate\n const consequent = findIconElement(expression.consequent);\n if (consequent) return consequent;\n\n const alternate = findIconElement(expression.alternate);\n if (alternate) return alternate;\n }\n\n return null;\n };\n\n // Skip empty JSX expressions like {}\n if (attr.value.expression.type === \"JSXEmptyExpression\") return;\n\n const iconElement = findIconElement(attr.value.expression);\n if (!iconElement) return;\n const iconSizeAttr = iconElement.attributes.find(\n (iconAttr): iconAttr is TSESTree.JSXAttribute =>\n iconAttr.type === \"JSXAttribute\" &&\n iconAttr.name.type === \"JSXIdentifier\" &&\n iconAttr.name.name === \"size\"\n );\n\n const iconSizeInfo = (() => {\n if (!iconSizeAttr?.value) return { type: \"implicit\", value: null };\n\n if (iconSizeAttr.value.type === \"Literal\" && typeof iconSizeAttr.value.value === \"string\") {\n return { type: \"literal\", value: iconSizeAttr.value.value };\n }\n\n if (iconSizeAttr.value.type === \"JSXExpressionContainer\") {\n const expr = iconSizeAttr.value.expression;\n if (expr.type === \"Identifier\") {\n return { type: \"variable\", value: expr.name, expression: expr };\n }\n return { type: \"expression\", value: null, expression: expr };\n }\n\n return { type: \"implicit\", value: null };\n })();\n\n // Rule: large buttons → medium icons, small/medium buttons → small icons\n const getExpectedIconSize = (buttonSize: string): string => {\n if (buttonSize === \"large\") return \"medium\";\n return \"small\"; // both \"small\" and \"medium\" buttons get \"small\" icons\n };\n\n const shouldReport = (() => {\n // For complex expressions, always warn but don't autofix\n if (buttonSizeInfo.type === \"expression\") {\n return true;\n }\n\n // For variables, check if icon already has the correct size\n if (buttonSizeInfo.type === \"variable\" && buttonSizeInfo.expression?.type === \"Identifier\") {\n const possibleSizes = getPossibleStringLiterals(context, buttonSizeInfo.expression);\n\n if (possibleSizes) {\n // Check if all possible button sizes map to the same icon size\n const iconSizes = possibleSizes.map(getExpectedIconSize);\n const uniqueIconSizes = [...new Set(iconSizes)];\n\n if (uniqueIconSizes.length === 1) {\n // All map to same icon size - check if icon already has correct literal\n const variableExpectedIconSize = uniqueIconSizes[0];\n const variableIconEffectiveSize = iconSizeInfo.value || \"medium\";\n\n if (variableIconEffectiveSize === variableExpectedIconSize) {\n return false; // Icon already has correct literal size\n }\n } else {\n // Mixed mapping - check if icon has correct conditional expression\n if (\n iconSizeInfo.type === \"expression\" &&\n iconSizeInfo.expression &&\n iconSizeInfo.expression.type !== \"JSXEmptyExpression\" &&\n buttonSizeInfo.value &&\n isCorrectConditionalExpression(iconSizeInfo.expression, buttonSizeInfo.value)\n ) {\n return false; // Icon already has correct conditional\n }\n }\n }\n\n // Mixed mapping or can't determine - always warn\n return true;\n }\n\n // For literals and implicit, check the mapping\n const buttonEffectiveSize = buttonSizeInfo.value || \"medium\";\n const iconEffectiveSize = iconSizeInfo.value || \"medium\";\n const expectedIconSize = getExpectedIconSize(buttonEffectiveSize);\n\n return iconEffectiveSize !== expectedIconSize;\n })();\n\n if (shouldReport) {\n context.report({\n node: iconElement,\n messageId: \"incorrectIconSize\",\n data: {\n expectedSize: (() => {\n if (buttonSizeInfo.type === \"variable\" && buttonSizeInfo.expression?.type === \"Identifier\") {\n // Analyze the variable's type to determine expected message\n const possibleSizes = getPossibleStringLiterals(context, buttonSizeInfo.expression);\n\n if (possibleSizes) {\n const iconSizes = possibleSizes.map(getExpectedIconSize);\n const uniqueIconSizes = [...new Set(iconSizes)];\n\n if (uniqueIconSizes.length === 1) {\n return uniqueIconSizes[0];\n }\n }\n\n return `{${buttonSizeInfo.value} === \"large\" ? \"medium\" : \"small\"}`;\n }\n if (buttonSizeInfo.type === \"expression\") {\n return \"small (for small/medium buttons) or medium (for large buttons)\";\n }\n const buttonEffectiveSize = buttonSizeInfo.value || \"medium\";\n return getExpectedIconSize(buttonEffectiveSize);\n })(),\n buttonSize:\n buttonSizeInfo.type === \"implicit\"\n ? \"medium (default)\"\n : buttonSizeInfo.type === \"literal\"\n ? buttonSizeInfo.value\n : buttonSizeInfo.type === \"variable\"\n ? (() => {\n if (buttonSizeInfo.expression?.type === \"Identifier\") {\n const possibleSizes = getPossibleStringLiterals(context, buttonSizeInfo.expression);\n if (possibleSizes && possibleSizes.length > 0) {\n const sizeList = possibleSizes.map(s => `\"${s}\"`).join(\" | \");\n return `{${buttonSizeInfo.value}} (of type ${sizeList})`;\n }\n }\n return `{${buttonSizeInfo.value}}`;\n })()\n : \"expression\",\n iconSize:\n iconSizeInfo.type === \"implicit\"\n ? \"medium (default)\"\n : iconSizeInfo.type === \"literal\"\n ? iconSizeInfo.value\n : iconSizeInfo.type === \"variable\"\n ? `{${iconSizeInfo.value}}`\n : \"expression\",\n },\n fix(fixer) {\n // Don't autofix complex expressions, only variables and literals\n if (buttonSizeInfo.type === \"expression\") {\n return null;\n }\n\n let targetSizeValue: string;\n\n if (buttonSizeInfo.type === \"variable\" && buttonSizeInfo.expression?.type === \"Identifier\") {\n // Analyze the variable's type to determine optimal autofix\n const possibleSizes = getPossibleStringLiterals(context, buttonSizeInfo.expression);\n\n if (possibleSizes) {\n // Check if all possible button sizes map to the same icon size\n const iconSizes = possibleSizes.map(getExpectedIconSize);\n const uniqueIconSizes = [...new Set(iconSizes)];\n\n if (uniqueIconSizes.length === 1) {\n // All possible button sizes map to the same icon size\n targetSizeValue = `\"${uniqueIconSizes[0]}\"`;\n } else {\n // Mixed mapping, use conditional\n targetSizeValue = `{${buttonSizeInfo.value} === \"large\" ? \"medium\" : \"small\"}`;\n }\n } else {\n // Can't determine type, use conditional\n targetSizeValue = `{${buttonSizeInfo.value} === \"large\" ? \"medium\" : \"small\"}`;\n }\n } else {\n // Calculate target icon size based on button size (literal or implicit)\n const buttonEffectiveSize = buttonSizeInfo.value || \"medium\";\n const targetIconSize = getExpectedIconSize(buttonEffectiveSize);\n targetSizeValue = `\"${targetIconSize}\"`;\n }\n\n if (iconSizeAttr) {\n // Replace existing size attribute\n if (!iconSizeAttr.value) return null;\n return fixer.replaceText(iconSizeAttr.value, targetSizeValue);\n } else {\n // Add size attribute\n const lastAttr = iconElement.attributes[iconElement.attributes.length - 1];\n if (lastAttr) {\n return fixer.insertTextAfter(lastAttr, ` size=${targetSizeValue}`);\n } else {\n return fixer.insertTextAfter(iconElement.name, ` size=${targetSizeValue}`);\n }\n }\n },\n });\n }\n }\n });\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-deprecated-graphql-fields.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/no-deprecated-graphql-fields/no-deprecated-graphql-fields.ts"],"names":[],"mappings":"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","sourcesContent":["import { ESLintUtils } from \"@typescript-eslint/utils\";\nimport * as fs from \"fs\";\nimport { NoDeprecatedCustomRule, parse, validate } from \"graphql\";\nimport * as path from \"path\";\nimport { findNearestFile } from \"../../utils/file-utils\";\nimport { getSchema } from \"./schema-cache\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}/${name}.ts`\n);\n\ntype MessageIds = \"deprecatedFieldUsed\";\ntype Options = [];\n\nconst EXCLUDED_DIRS = new Set([\"node_modules\", \"generated\", \"dist\"]);\n\nconst collectGraphqlFiles = (dir: string, files: Array<string> = []): Array<string> => {\n let entries: Array<fs.Dirent>;\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return files;\n }\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n let stat: fs.Stats;\n try {\n stat = fs.statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (!EXCLUDED_DIRS.has(entry.name)) {\n collectGraphqlFiles(fullPath, files);\n }\n } else if (entry.name.endsWith(\".graphql\")) {\n files.push(fullPath);\n }\n }\n return files;\n};\n\nexport const noDeprecatedGraphqlFields = createRule<Options, MessageIds>({\n name: \"no-deprecated-graphql-fields\",\n meta: {\n type: \"problem\",\n docs: {\n description: \"Disallow usage of @deprecated GraphQL fields in .graphql operation files\",\n },\n messages: {\n deprecatedFieldUsed: \"Deprecated GraphQL field used in {{file}}: {{message}}\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n return {\n Program: _node => {\n const sourceFilePath = context.filename;\n if (!sourceFilePath.endsWith(\"/project.json\")) {\n return;\n }\n\n const nxJsonPath = findNearestFile(sourceFilePath, \"nx.json\");\n if (!nxJsonPath) {\n return;\n }\n const monorepoRoot = path.dirname(nxJsonPath);\n\n const schemaPath = path.join(\n monorepoRoot,\n \"libs\",\n \"api\",\n \"internal-gql-schema\",\n \"generated\",\n \"internal-schema.gql\"\n );\n\n const schema = getSchema(schemaPath);\n if (!schema) {\n return;\n }\n\n const projectDir = path.dirname(sourceFilePath);\n const graphqlFiles = collectGraphqlFiles(projectDir);\n\n for (const gqlFile of graphqlFiles) {\n let content: string;\n try {\n content = fs.readFileSync(gqlFile, \"utf8\");\n } catch {\n continue;\n }\n\n let document;\n try {\n document = parse(content);\n } catch {\n continue;\n }\n\n const errors = validate(schema, document, [NoDeprecatedCustomRule]);\n for (const error of errors) {\n context.report({\n messageId: \"deprecatedFieldUsed\",\n data: {\n file: path.relative(monorepoRoot, gqlFile),\n message: error.message,\n },\n loc: { line: 1, column: 0 },\n });\n }\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema-cache.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/no-deprecated-graphql-fields/schema-cache.ts"],"names":[],"mappings":";;;;AAAA,+CAAyB;AACzB,qCAA0D;AAE1D;;;GAGG;AACH,MAAM,WAAW,GAAG,IAAI,GAAG,EAAyB,CAAC;AAE9C,MAAM,SAAS,GAAG,CAAC,UAAkB,EAAwB,EAAE;IACpE,IAAI,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAChC,OAAO,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;IAC7C,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,IAAA,qBAAW,EAAC,OAAO,CAAC,CAAC;QACpC,WAAW,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACpC,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAZW,QAAA,SAAS,aAYpB;AAEK,MAAM,gBAAgB,GAAG,GAAS,EAAE;IACzC,WAAW,CAAC,KAAK,EAAE,CAAC;AACtB,CAAC,CAAC;AAFW,QAAA,gBAAgB,oBAE3B","sourcesContent":["import * as fs from \"fs\";\nimport { type GraphQLSchema, buildSchema } from \"graphql\";\n\n/**\n * Caches parsed schemas by path to avoid re-parsing on every project.json lint.\n * Isolated in its own module so tests can reset it independently of the rule's production exports.\n */\nconst schemaCache = new Map<string, GraphQLSchema>();\n\nexport const getSchema = (schemaPath: string): GraphQLSchema | null => {\n if (schemaCache.has(schemaPath)) {\n return schemaCache.get(schemaPath) ?? null;\n }\n try {\n const content = fs.readFileSync(schemaPath, \"utf8\");\n const schema = buildSchema(content);\n schemaCache.set(schemaPath, schema);\n return schema;\n } catch {\n return null;\n }\n};\n\nexport const clearSchemaCache = (): void => {\n schemaCache.clear();\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-dynamic-translation-key.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/no-dynamic-translation-key/no-dynamic-translation-key.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ESLint rule that discourages building i18next translation keys dynamically\n * with template strings (e.g. `t(`pages.categories.${category}`)`).\n *\n * Dynamic keys are impossible to analyse statically: they defeat the typed\n * translation-key safety and make it impossible to tell which keys in a\n * `translation.json` are actually used. Mapping the value to an explicit key\n * with a `switch` statement or a `Record` keeps keys statically analysable and\n * lets `no-unused-translation-key` detect orphaned translations.\n *\n * @example\n * // Bad\n * t(`pages.categories.${category}`);\n * <Trans i18nKey={`pages.categories.${category}`} />;\n *\n * // Good\n * const categoryKey: Record<Category, TranslationKeys> = { ... };\n * t(categoryKey[category]);\n */\nimport { AST_NODE_TYPES, ESLintUtils, type TSESLint, TSESTree } from \"@typescript-eslint/utils\";\nimport { classifyInterpolationType } from \"../../utils/translation-key-types\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}/${name}.ts`\n);\n\ntype MessageIds = \"dynamicKey\";\ntype Options = [];\n\n/** A template literal that actually interpolates a value, e.g. `foo.${bar}` (not a plain `foo`). */\nconst isInterpolatedTemplate = (node: TSESTree.Node): node is TSESTree.TemplateLiteral =>\n node.type === AST_NODE_TYPES.TemplateLiteral && node.expressions.length > 0;\n\n/**\n * Strips `as`/`satisfies`/non-null/`<T>`-assertion wrappers to reach the underlying expression.\n *\n * `` t(`a.${x}` as never) `` parses as a `TSAsExpression` whose `.expression` is the real\n * `TemplateLiteral`, so without this the wrapper silently hides the dynamic key from the rule.\n * That is an escape hatch we must not offer: casting a widened interpolation is exactly what this\n * rule exists to forbid, and the sibling `no-unused-translation-key` already unwraps the same\n * wrappers (see its `expand-dynamic-key.ts#unwrapToTemplateExpression`), so leaving them here means\n * one rule sees the key and the other does not.\n */\nconst unwrapTypeWrappers = (node: TSESTree.Node): TSESTree.Node => {\n let current = node;\n while (\n current.type === AST_NODE_TYPES.TSAsExpression ||\n current.type === AST_NODE_TYPES.TSSatisfiesExpression ||\n current.type === AST_NODE_TYPES.TSNonNullExpression ||\n current.type === AST_NODE_TYPES.TSTypeAssertion\n ) {\n current = current.expression;\n }\n return current;\n};\n\n/**\n * Whether a template literal's interpolations should be flagged: true unless every\n * interpolated expression's TypeScript type is a finite string-literal union (in which\n * case every possible resulting key is statically enumerable). If type resolution fails\n * for any reason (e.g. a non-type-aware lint run), fails safe by flagging the template.\n */\nconst hasWidenedInterpolation = (\n context: TSESLint.RuleContext<MessageIds, Options>,\n templateLiteral: TSESTree.TemplateLiteral\n): boolean => {\n try {\n const services = ESLintUtils.getParserServices(context);\n const checker = services.program.getTypeChecker();\n\n return templateLiteral.expressions.some(expr => {\n const tsNode = services.esTreeNodeToTSNodeMap.get(expr);\n const type = checker.getTypeAtLocation(tsNode);\n return classifyInterpolationType(type) === \"widened\";\n });\n } catch {\n return true;\n }\n};\n\n/** A call to the translation function: either a bare `t(...)` or a member call like `i18n.t(...)`. */\nconst isTranslationCallee = (callee: TSESTree.Node): boolean => {\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name === \"t\";\n }\n return (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n !callee.computed &&\n callee.property.type === AST_NODE_TYPES.Identifier &&\n callee.property.name === \"t\"\n );\n};\n\nexport const noDynamicTranslationKey = createRule<Options, MessageIds>({\n name: \"no-dynamic-translation-key\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Disallow building i18next translation keys dynamically with template strings; map values to explicit keys with a switch or Record instead.\",\n },\n messages: {\n dynamicKey:\n \"Avoid building translation keys dynamically with template strings unless every interpolated value has a finite string-literal union type (TypeScript can then enumerate every possible key). Otherwise, map the value to an explicit key using a switch statement or a Record so keys stay statically analysable and unused keys can be detected.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node) {\n if (!isTranslationCallee(node.callee)) {\n return;\n }\n const [firstArg] = node.arguments;\n if (!firstArg) {\n return;\n }\n const key = unwrapTypeWrappers(firstArg);\n if (isInterpolatedTemplate(key) && hasWidenedInterpolation(context, key)) {\n context.report({ node: key, messageId: \"dynamicKey\" });\n }\n },\n JSXAttribute(node) {\n if (node.name.type !== AST_NODE_TYPES.JSXIdentifier || node.name.name !== \"i18nKey\") {\n return;\n }\n const { value } = node;\n if (value?.type !== AST_NODE_TYPES.JSXExpressionContainer) {\n return;\n }\n const key = unwrapTypeWrappers(value.expression);\n if (isInterpolatedTemplate(key) && hasWidenedInterpolation(context, key)) {\n context.report({ node: key, messageId: \"dynamicKey\" });\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-internal-barrel-files.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/no-internal-barrel-files/no-internal-barrel-files.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ESLint rule to disallow internal barrel files.\n *\n * Internal barrel files (any index.ts or index.tsx that is not at the library root) cause:\n * - Multiple import paths to the same module\n * - Slower builds (bundlers must traverse more barrel files)\n * - Confusion about canonical import paths\n * - Potential bundle size issues\n * - Module identity problems\n *\n * EXCEPTION: Secondary entry points configured in tsconfig.base.json are allowed.\n * These are intentional barrel files that provide separate package imports\n * (e.g., @trackunit/react-core-contexts-host-test pointing to src/test/index.ts).\n *\n * @example\n * // Valid - Root barrel file\n * // libs/my-lib/src/index.ts ✅\n *\n * // Valid - Secondary entry point configured in tsconfig.base.json\n * // libs/my-lib/src/test/index.ts ✅ (if configured as @trackunit/my-lib-test)\n *\n * // Invalid - Internal barrel file\n * // libs/my-lib/src/components/index.ts ❌\n * // libs/my-lib/src/utils/helpers/index.ts ❌\n */\nimport { ESLintUtils } from \"@typescript-eslint/utils\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { z } from \"zod\";\nimport { findNearestFile } from \"../../utils/file-utils\";\n\nconst projectJsonSchema = z.object({\n sourceRoot: z.string().optional(),\n});\n\nconst tsconfigSchema = z.object({\n compilerOptions: z\n .object({\n paths: z.record(z.array(z.string())).optional(),\n })\n .optional(),\n});\n\n/**\n * Cache for tsconfig.base.json secondary entry points.\n * Key: workspace root path\n * Value: Set of absolute paths to allowed secondary entry points\n */\nconst secondaryEntryPointsCache = new Map<string, Set<string>>();\n\n/**\n * Find the workspace root by looking for nx.json\n */\nconst findWorkspaceRoot = (startPath: string): string | null => {\n const nxJsonPath = findNearestFile(startPath, \"nx.json\");\n return nxJsonPath ? path.dirname(nxJsonPath) : null;\n};\n\n/**\n * Get secondary entry points from tsconfig.base.json.\n * These are path mappings that point to index.ts files inside src/ subdirectories.\n * Results are cached per workspace root.\n */\nconst getSecondaryEntryPoints = (workspaceRoot: string): Set<string> => {\n const cached = secondaryEntryPointsCache.get(workspaceRoot);\n if (cached) {\n return cached;\n }\n\n const entryPoints = new Set<string>();\n const tsconfigPath = path.join(workspaceRoot, \"tsconfig.base.json\");\n\n try {\n const tsconfigContent = fs.readFileSync(tsconfigPath, \"utf-8\");\n const parsed = tsconfigSchema.safeParse(JSON.parse(tsconfigContent));\n\n if (parsed.success && parsed.data.compilerOptions?.paths) {\n const paths = parsed.data.compilerOptions.paths;\n\n for (const pathMappings of Object.values(paths)) {\n for (const mapping of pathMappings) {\n // Only consider mappings that point to index.ts files\n if (mapping.endsWith(\"/index.ts\") || mapping.endsWith(\"/index.tsx\")) {\n const absolutePath = path.normalize(path.join(workspaceRoot, mapping));\n entryPoints.add(absolutePath);\n }\n }\n }\n }\n } catch {\n // If we can't read tsconfig.base.json, return empty set\n }\n\n secondaryEntryPointsCache.set(workspaceRoot, entryPoints);\n return entryPoints;\n};\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}.ts`\n);\n\ntype MessageIds = \"noInternalBarrel\";\ntype Options = [];\n\n/**\n * Check if a file is a barrel file (index.ts or index.tsx).\n */\nconst isBarrelFile = (filePath: string): boolean => {\n const basename = path.basename(filePath);\n return basename === \"index.ts\" || basename === \"index.tsx\";\n};\n\n/**\n * Normalize file path for comparison (handles potential trailing slashes, etc.)\n */\nconst normalizePath = (filePath: string): string => {\n return path.normalize(filePath);\n};\n\nexport const noInternalBarrelFiles = createRule<Options, MessageIds>({\n name: \"no-internal-barrel-files\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Disallow internal barrel files (index.ts) that are not at the library root or configured as secondary entry points\",\n },\n schema: [],\n messages: {\n noInternalBarrel:\n \"Internal barrel files are not allowed. Move exports to the root barrel file (src/index.ts) instead. Use the flatten-barrel-exports tool: yarn ts-node devtools/flatten-barrel-exports/flatten-barrel-exports.ts\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n Program(node) {\n const currentFile = context.filename;\n\n // Only analyze barrel files (index.ts/tsx)\n if (!isBarrelFile(currentFile)) {\n return;\n }\n\n // Find the project root by looking for project.json\n const projectJsonPath = findNearestFile(currentFile, \"project.json\");\n if (projectJsonPath === null) {\n // Not in an NX project, skip\n return;\n }\n\n const projectRoot = path.dirname(projectJsonPath);\n const workspaceRoot = findWorkspaceRoot(currentFile);\n\n // Read sourceRoot from project.json, defaulting to \"src\" if not specified\n // sourceRoot in project.json is relative to workspace root (e.g., \"libs/my-lib/src\")\n let sourceRootAbsolute = path.join(projectRoot, \"src\");\n try {\n const projectJsonContent = fs.readFileSync(projectJsonPath, \"utf-8\");\n const parsed = projectJsonSchema.safeParse(JSON.parse(projectJsonContent));\n if (parsed.success && parsed.data.sourceRoot && workspaceRoot) {\n // sourceRoot is relative to workspace root, so resolve it\n sourceRootAbsolute = path.join(workspaceRoot, parsed.data.sourceRoot);\n }\n } catch {\n // If we can't read project.json, fall back to projectRoot/src\n }\n\n // The root barrel is at {sourceRoot}/index.ts or {sourceRoot}/index.tsx\n const rootBarrelTs = normalizePath(path.join(sourceRootAbsolute, \"index.ts\"));\n const rootBarrelTsx = normalizePath(path.join(sourceRootAbsolute, \"index.tsx\"));\n const normalizedCurrentFile = normalizePath(currentFile);\n\n // If this IS the root barrel, it's allowed\n if (normalizedCurrentFile === rootBarrelTs || normalizedCurrentFile === rootBarrelTsx) {\n return;\n }\n\n // Check if this is a secondary entry point configured in tsconfig.base.json\n if (workspaceRoot) {\n const secondaryEntryPoints = getSecondaryEntryPoints(workspaceRoot);\n if (secondaryEntryPoints.has(normalizedCurrentFile)) {\n // This is a configured secondary entry point, allow it\n return;\n }\n }\n\n // This is an internal barrel file - flag it\n // Note: No autofix or suggestion is provided because:\n // 1. The exports need to be moved to the root barrel\n // 2. Imports throughout the codebase may need updating\n // 3. The flatten-barrel-exports tool handles this properly\n context.report({\n node,\n messageId: \"noInternalBarrel\",\n });\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-internal-graphql-when-tagged-with-gql-public.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public.ts"],"names":[],"mappings":"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","sourcesContent":["import { ESLintUtils } from \"@typescript-eslint/utils\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}/${name}.ts`\n);\n\ntype MessageIds = \"internalGraphqlFileFound\";\ntype Options = [];\n\nexport const noInternalGraphqlWhenTaggedWithGqlPublic = createRule<Options, MessageIds>({\n name: \"no-internal-graphql-when-tagged-with-gql-public\",\n meta: {\n type: \"problem\",\n docs: {\n description: \"Disallow '-internal.graphql' files in projects tagged with 'gql:public'\",\n },\n messages: {\n internalGraphqlFileFound: \"'*-internal.graphql' file found in a 'gql:public' tagged project. - {{path}}\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const getLineAndColumnFromPosition = (content: string, position: number) => {\n const lines = content.substring(0, position).split(\"\\n\");\n const line = lines.length;\n const column = lines[lines.length - 1]?.length ?? 0;\n return { line, column };\n };\n\n const checkDirectoryForInternalGraphQLFiles = (directory: string, projectJson: string) => {\n const entries = fs.readdirSync(directory, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(directory, entry.name);\n\n // Handle broken symlinks or inaccessible paths gracefully\n let stat: fs.Stats;\n try {\n stat = fs.statSync(fullPath);\n } catch {\n // Skip paths that can't be accessed (broken symlinks, permission issues, etc.)\n continue;\n }\n\n if (stat.isDirectory()) {\n checkDirectoryForInternalGraphQLFiles(fullPath, projectJson);\n } else if (entry.name.endsWith(\"-internal.graphql\")) {\n context.report({\n messageId: \"internalGraphqlFileFound\",\n data: { path: fullPath },\n loc: getLineAndColumnFromPosition(projectJson, projectJson.indexOf(\"gql:public\")),\n });\n return;\n }\n }\n };\n return {\n Program: _node => {\n const sourceFilePath = context.filename;\n if (sourceFilePath.endsWith(\"/project.json\")) {\n const projectJsonString = fs.readFileSync(sourceFilePath, \"utf8\");\n const projectJson: { tags?: Array<string> } = JSON.parse(projectJsonString);\n if (Array.isArray(projectJson.tags) && projectJson.tags.includes(\"gql:public\")) {\n const projectDir = path.dirname(sourceFilePath);\n checkDirectoryForInternalGraphQLFiles(projectDir, projectJsonString);\n }\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-jest-mock-trackunit-react-core-hooks.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks.ts"],"names":[],"mappings":";;;AAAA,oDAAuD;AAEvD,MAAM,UAAU,GAAG,mBAAW,CAAC,WAAW,CACxC,IAAI,CAAC,EAAE,CACL,6FAA6F,IAAI,IAAI,IAAI,KAAK,CACjH,CAAC;AAKW,QAAA,iCAAiC,GAAG,UAAU,CAAsB;IAC/E,IAAI,EAAE,yCAAyC;IAC/C,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,4DAA4D;SAC1E;QACD,QAAQ,EAAE;YACR,YAAY,EACV,oKAAoK;SACvK;QACD,MAAM,EAAE,EAAE;KACX;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,cAAc,CAAC,IAAI;gBACjB,IACE,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB;oBACvC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;oBACxC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM;oBAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;oBAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM;oBACpC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,SAAS;oBACrC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,6BAA6B,EACzD,CAAC;oBACD,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,cAAc;qBAC1B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["import { ESLintUtils } from \"@typescript-eslint/utils\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name =>\n `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}/${name}.ts`\n);\n\ntype MessageIds = \"noDirectMock\";\ntype Options = [];\n\nexport const noJestMockTrackunitReactCoreHooks = createRule<Options, MessageIds>({\n name: \"no-jest-mock-trackunit-react-core-hooks\",\n meta: {\n type: \"problem\",\n docs: {\n description: \"Disallow direct jest.mock() of @trackunit/react-core-hooks\",\n },\n messages: {\n noDirectMock:\n 'Don\\'t use jest.mock(\"@trackunit/react-core-hooks\"). Use mock builder from trackunitProviders(), trackunitProvidersInternal() or trackunitProvidersHost() instead.',\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node) {\n if (\n node.callee.type === \"MemberExpression\" &&\n node.callee.object.type === \"Identifier\" &&\n node.callee.object.name === \"jest\" &&\n node.callee.property.type === \"Identifier\" &&\n node.callee.property.name === \"mock\" &&\n node.arguments[0]?.type === \"Literal\" &&\n node.arguments[0].value === \"@trackunit/react-core-hooks\"\n ) {\n context.report({\n node,\n messageId: \"noDirectMock\",\n });\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-template-strings-in-classname-prop.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop.ts"],"names":[],"mappings":";;;AAAA,wEAAsG;AACtG,oDAAiF;AAEjF,MAAM,UAAU,GAAG,mBAAW,CAAC,WAAW,CACxC,IAAI,CAAC,EAAE,CAAC,6FAA6F,IAAI,KAAK,CAC/G,CAAC;AAKF;;;;;;;;;;;GAWG;AACU,QAAA,4BAA4B,GAAG,UAAU,CAAsB;IAC1E,IAAI,EAAE,uCAAuC;IAC7C,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EAAE,8FAA8F;SAC5G;QACD,QAAQ,EAAE;YACR,yBAAyB,EACvB,+LAA+L;SAClM;QACD,MAAM,EAAE,EAAE;KACX;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,OAAO;YACL;;;;;;eAMG;YACH,YAAY,CAAC,IAA2B;gBACtC,8DAA8D;gBAC9D,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,aAAa,IAAI,CAAC,IAAA,0CAAoB,EAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7F,OAAO;gBACT,CAAC;gBAED,yEAAyE;gBACzE,IACE,IAAI,CAAC,KAAK,EAAE,IAAI,KAAK,sBAAc,CAAC,sBAAsB;oBAC1D,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,KAAK,sBAAc,CAAC,eAAe,EAC7D,CAAC;oBACD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,2BAA2B,EAAE,CAAC,CAAC;gBACnE,CAAC;YACH,CAAC;YAED,kBAAkB,CAAC,IAAiC;gBAClD,MAAM,SAAS,GAAG,IAAA,oDAA8B,EAAC,IAAI,CAAC,CAAC;gBACvD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;oBACjC,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,sBAAc,CAAC,eAAe,EAAE,CAAC;wBAC7D,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,EAAE,SAAS,EAAE,2BAA2B,EAAE,CAAC,CAAC;oBACxF,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["import { findClassnameStringsInVariable, isClassnameAttribute } from \"@trackunit/css-classname-utils\";\nimport { AST_NODE_TYPES, ESLintUtils, 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 MessageIds = \"templateStringInClassName\";\ntype Options = [];\n\n/**\n * ESLint rule to disallow template strings in className prop.\n *\n * @example\n * // Bad\n * <div className={`${dynamicClass} staticClass`}>Content</div>\n *\n * // Good\n * <div className={twMerge(dynamicClassName, \"staticClassName\")}>Content</div>\n * // or\n * <div className={yourCvaMergeFunction({ yourVariantProp, className: \"extraClassName\" })}>Content</div>\n */\nexport const noTemplateStringsInClassName = createRule<Options, MessageIds>({\n name: \"no-template-strings-in-classname-prop\",\n meta: {\n type: \"suggestion\",\n docs: {\n description: \"Disallow the use of template strings in className prop to encourage better class management.\",\n },\n messages: {\n templateStringInClassName:\n \"Do not use template strings in className prop. If you wish to merge classes from different sources, use twMerge() for simple inline merging or make a cvaMerge() function if it has variants.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n return {\n /**\n * Handle JSXAttribute with className prop that uses template strings.\n *\n * @example\n * // Bad\n * <div className={`${dynamicClass} staticClass`}>Content</div>\n */\n JSXAttribute(node: TSESTree.JSXAttribute) {\n // Check if this is a classname attribute (className or class)\n if (node.name.type !== AST_NODE_TYPES.JSXIdentifier || !isClassnameAttribute(node.name.name)) {\n return;\n }\n\n // Check if the value is a template literal in a JSX expression container\n if (\n node.value?.type === AST_NODE_TYPES.JSXExpressionContainer &&\n node.value.expression.type === AST_NODE_TYPES.TemplateLiteral\n ) {\n context.report({ node, messageId: \"templateStringInClassName\" });\n }\n },\n\n VariableDeclarator(node: TSESTree.VariableDeclarator) {\n const locations = findClassnameStringsInVariable(node);\n for (const location of locations) {\n if (location.fixNode.type === AST_NODE_TYPES.TemplateLiteral) {\n context.report({ node: location.reportNode, messageId: \"templateStringInClassName\" });\n }\n }\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-typescript-assertion.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/no-typescript-assertion/no-typescript-assertion.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;GAcG;AACH,oDAAiF;AAEjF,MAAM,UAAU,GAAG,mBAAW,CAAC,WAAW,CACxC,IAAI,CAAC,EAAE,CAAC,6FAA6F,IAAI,IAAI,IAAI,KAAK,CACvH,CAAC;AAKF,SAAS,sBAAsB,CAAC,cAAiC;IAC/D,IAAI,cAAc,CAAC,IAAI,KAAK,sBAAc,CAAC,gBAAgB,EAAE,CAAC;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,cAAc,CAAC,IAAI,KAAK,sBAAc,CAAC,eAAe,EAAE,CAAC;QAC3D,MAAM,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAC;QACpC,IAAI,QAAQ,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC7E,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAEY,QAAA,qBAAqB,GAAG,UAAU,CAAsB;IACnE,IAAI,EAAE,yBAAyB;IAC/B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EAAE,qEAAqE;SACnF;QACD,QAAQ,EAAE;YACR,qBAAqB,EAAE,wEAAwE;YAC/F,WAAW,EAAE,2EAA2E;YACxF,gBAAgB,EAAE,iFAAiF;SACpG;QACD,MAAM,EAAE,EAAE;KACX;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,eAAe,CAAC,IAA8B;gBAC5C,IAAI,sBAAsB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;oBAChD,OAAO;gBACT,CAAC;gBACD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,uBAAuB,EAAE,CAAC,CAAC;YAC/D,CAAC;YACD,cAAc,CAAC,IAA6B;gBAC1C,IAAI,sBAAsB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;oBAChD,OAAO;gBACT,CAAC;gBACD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;YACrD,CAAC;YACD,mBAAmB,CAAC,IAAkC;gBACpD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC1D,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["/**\n * ESLint rule to disallow type assertions in TypeScript.\n * Initial implementation based on eslint-plugin-no-type-assertion\n * https://github.com/Dremora/eslint-plugin-no-type-assertion/blob/master/lib/rules/no-type-assertion.js\n *\n * @example\n * // Bad - type assertions bypass type checking\n * const foo = <string> bar;\n * const baz = bar as string;\n * const qux = bar!;\n *\n * // Good - proper typing or const assertions\n * const foo = bar;\n * const options = [\"a\", \"b\"] as const;\n */\nimport { AST_NODE_TYPES, ESLintUtils, 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}/${name}.ts`\n);\n\ntype MessageIds = \"angleBracketAssertion\" | \"asAssertion\" | \"nonNullAssertion\";\ntype Options = [];\n\nfunction isAllowedTypeAssertion(typeAnnotation: TSESTree.TypeNode): boolean {\n if (typeAnnotation.type === AST_NODE_TYPES.TSUnknownKeyword) {\n return true;\n }\n if (typeAnnotation.type === AST_NODE_TYPES.TSTypeReference) {\n const { typeName } = typeAnnotation;\n if (typeName.type === AST_NODE_TYPES.Identifier && typeName.name === \"const\") {\n return true;\n }\n }\n return false;\n}\n\nexport const noTypescriptAssertion = createRule<Options, MessageIds>({\n name: \"no-typescript-assertion\",\n meta: {\n type: \"suggestion\",\n docs: {\n description: \"Prevent the use of type assertions to encourage better type safety.\",\n },\n messages: {\n angleBracketAssertion: \"Avoid using angle bracket for type casting. It bypasses type checking.\",\n asAssertion: \"Avoid using the `as` keyword for type casting. It bypasses type checking.\",\n nonNullAssertion: \"Avoid using the non-null assertion operator (!). It can lead to runtime errors.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n return {\n TSTypeAssertion(node: TSESTree.TSTypeAssertion) {\n if (isAllowedTypeAssertion(node.typeAnnotation)) {\n return;\n }\n context.report({ node, messageId: \"angleBracketAssertion\" });\n },\n TSAsExpression(node: TSESTree.TSAsExpression) {\n if (isAllowedTypeAssertion(node.typeAnnotation)) {\n return;\n }\n context.report({ node, messageId: \"asAssertion\" });\n },\n TSNonNullExpression(node: TSESTree.TSNonNullExpression) {\n context.report({ node, messageId: \"nonNullAssertion\" });\n },\n };\n },\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"expand-dynamic-key.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/no-unused-translation-key/expand-dynamic-key.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Type-aware expansion of dynamic (template-literal) translation keys.\n *\n * `used-strings.ts` detects dynamic keys via regex over raw source text, producing a\n * `{ prefix, suffix }` wildcard pattern that conservatively treats every key matching that\n * prefix/suffix as \"used\". This module replaces that conservative pattern with the exact set of\n * concrete keys whenever every interpolation in a direct `t(...)`/`i18nKey={...}` template\n * literal is a finite string-literal union — `` t(`cat.${category}`) `` with\n * `category: \"A\" | \"B\"` becomes `[\"cat.A\", \"cat.B\"]` instead of `{ prefix: \"cat.\", suffix: \"\" }`.\n *\n * This walks a real `ts.Program` (see `program-utils.ts`) directly, independent of ESLint's own\n * per-file visitor, because it needs to examine every file in a library — not just the one file\n * ESLint happens to be linting when it asks \"is this key used?\".\n *\n * Indirect/variable-built keys (`const key = \\`a.${x}\\`; t(key)`) are out of scope here and stay on\n * the existing regex path in `used-strings.ts` — this only matches template literals written\n * directly inside the call/attribute, mirroring the restriction `no-dynamic-translation-key`\n * itself enforces.\n */\nimport * as path from \"path\";\nimport * as ts from \"typescript\";\nimport { classifyInterpolationType } from \"../../utils/translation-key-types\";\n\n/**\n * The result of expanding one direct `t(...)`/`i18nKey={...}` template-literal call:\n * - `concrete` — every interpolation was a finite string-literal union, so every possible key is\n * enumerated exactly.\n * - `pattern` — at least one interpolation widened to `string`/`any`/`unknown`/an enum, so we fall\n * back to today's conservative prefix/suffix wildcard.\n */\nexport type ExpandedDynamicKey =\n | { kind: \"concrete\"; keys: Array<string> }\n | { kind: \"pattern\"; prefix: string; suffix: string };\n\nconst EXCLUDED_PATH_SEGMENTS = [\"/node_modules/\", \"/dist/\", \"/generated/\", \"/coverage/\", \"/.git/\"];\n\n// Type guard for TypeScript API. Mirrors `translation-key-types.ts`'s `isFiniteStringLiteralType`:\n// excludes `EnumLiteral` members, since string enum members carry both the `StringLiteral` and\n// `EnumLiteral` flags and enums are out of scope for concrete expansion (see Phase 1).\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 * Extracts the exact string values of a finite string-literal type or union thereof.\n *\n * A union may also carry an `undefined` member (see `classifyInterpolationType`, which still\n * classifies such a union as `literalUnion` as long as every *other* member is a string literal).\n * A real call site with that interpolation `undefined` produces the runtime string `\"undefined\"` --\n * JS template literals stringify `undefined` to the text \"undefined\" -- so that literal string is\n * included as one of the concrete values, alongside the real string-literal members.\n */\nconst getLiteralStringValues = (type: ts.Type): Array<string> => {\n if (type.isUnion()) {\n const literalValues = type.types.filter(isFiniteStringLiteralType).map(member => member.value);\n const hasUndefinedMember = type.types.some(member => (member.getFlags() & ts.TypeFlags.Undefined) !== 0);\n return hasUndefinedMember ? [...literalValues, \"undefined\"] : literalValues;\n }\n return isFiniteStringLiteralType(type) ? [type.value] : [];\n};\n\n/** A call to the translation function: either a bare `t(...)` or a member call like `i18n.t(...)`. */\nconst isTranslationCalleeNode = (callee: ts.Expression): boolean => {\n if (ts.isIdentifier(callee)) {\n return callee.text === \"t\";\n }\n return ts.isPropertyAccessExpression(callee) && callee.name.text === \"t\";\n};\n\n/** Today's conservative prefix/suffix wildcard: the static text before the first, and after the last, interpolation. */\nconst buildPatternFallback = (template: ts.TemplateExpression): ExpandedDynamicKey => {\n const spans = template.templateSpans;\n const lastSpan = spans[spans.length - 1];\n return {\n kind: \"pattern\",\n prefix: template.head.text,\n suffix: lastSpan ? lastSpan.literal.text : \"\",\n };\n};\n\n/**\n * Expands one direct template-literal call: concrete cross-product if every interpolation is a\n * finite string-literal union, otherwise the prefix/suffix fallback. Fails safe to the fallback\n * if type resolution throws for this call site, so one bad call can't crash the whole scan.\n */\nconst expandTemplate = (template: ts.TemplateExpression, checker: ts.TypeChecker): ExpandedDynamicKey => {\n try {\n const interpolations: Array<{ values: Array<string>; literalText: string }> = [];\n\n for (const span of template.templateSpans) {\n const type = checker.getTypeAtLocation(span.expression);\n if (classifyInterpolationType(type) !== \"literalUnion\") {\n return buildPatternFallback(template);\n }\n const values = getLiteralStringValues(type);\n if (values.length === 0) {\n return buildPatternFallback(template);\n }\n interpolations.push({ values, literalText: span.literal.text });\n }\n\n let keys: Array<string> = [template.head.text];\n for (const { values, literalText } of interpolations) {\n const next: Array<string> = [];\n for (const key of keys) {\n for (const value of values) {\n next.push(key + value + literalText);\n }\n }\n keys = next;\n }\n\n return { kind: \"concrete\", keys };\n } catch {\n return buildPatternFallback(template);\n }\n};\n\n/**\n * Unwraps `as`/`satisfies`/parenthesized wrappers to find a `TemplateExpression` underneath.\n *\n * `` t(`cat.${x}` as const) `` parses as an `AsExpression` whose `.expression` is the actual\n * `TemplateExpression` — the wrapper is invisible to a direct `ts.isTemplateExpression(node)` check,\n * even though the checker still reports a type for the inner expression regardless of the wrapper\n * (see `expandTemplate`'s use of `checker.getTypeAtLocation(span.expression)`, which is unaffected by\n * unwrapping here since spans live inside the returned node either way).\n */\nconst unwrapToTemplateExpression = (node: ts.Node): ts.TemplateExpression | null => {\n let current = node;\n while (ts.isAsExpression(current) || ts.isSatisfiesExpression(current) || ts.isParenthesizedExpression(current)) {\n current = current.expression;\n }\n return ts.isTemplateExpression(current) ? current : null;\n};\n\n/**\n * Whether a JSX attribute is `i18nKey={...}` with a template-literal expression inside the braces.\n */\nconst getI18nKeyTemplate = (node: ts.JsxAttribute): ts.TemplateExpression | null => {\n if (!ts.isIdentifier(node.name) || node.name.text !== \"i18nKey\") {\n return null;\n }\n const { initializer } = node;\n if (initializer && ts.isJsxExpression(initializer) && initializer.expression) {\n return unwrapToTemplateExpression(initializer.expression);\n }\n return null;\n};\n\n/** Finds every direct `t(`...${...}...`)`/`i18nKey={`...${...}...`}` template literal in a source file. */\nconst collectDirectTemplates = (sourceFile: ts.SourceFile): Array<ts.TemplateExpression> => {\n const templates: Array<ts.TemplateExpression> = [];\n\n const visit = (node: ts.Node): void => {\n if (ts.isCallExpression(node) && isTranslationCalleeNode(node.expression)) {\n const [firstArg] = node.arguments;\n const template = firstArg && unwrapToTemplateExpression(firstArg);\n if (template) {\n templates.push(template);\n }\n } else if (ts.isJsxAttribute(node)) {\n const template = getI18nKeyTemplate(node);\n if (template) {\n templates.push(template);\n }\n }\n\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return templates;\n};\n\n/**\n * Whether a source file belongs to the library's own real source — not a declaration file, a\n * vendored/build artifact, or a file pulled into the `Program` only because the library imports it\n * (`ts.createProgram` includes every file transitively reachable from `rootNames`, which in this\n * monorepo's path-mapped setup means every other library the library under scan depends on).\n * `projectDirPrefix` restricts the scan back to files actually inside the library being linted, so a\n * dependency's own `t(...)` calls aren't misattributed as this library's usage (and aren't re-walked\n * on every dependent library's lint pass).\n */\nconst isScannableSourceFile = (sourceFile: ts.SourceFile, projectDirPrefix: string): boolean => {\n if (sourceFile.isDeclarationFile) {\n return false;\n }\n const fileName = sourceFile.fileName.replace(/\\\\/g, \"/\");\n if (!/\\.tsx?$/.test(fileName)) {\n return false;\n }\n if (!fileName.startsWith(projectDirPrefix)) {\n return false;\n }\n return !EXCLUDED_PATH_SEGMENTS.some(segment => fileName.includes(segment));\n};\n\n/**\n * Walks every real source file belonging to `projectDir` within `program`, expanding each direct\n * `t(...)`/`i18nKey={...}` template-literal call into either its exact concrete keys or a\n * conservative prefix/suffix pattern (see `ExpandedDynamicKey`).\n *\n * `program` may contain many more files than just this library's own — see `isScannableSourceFile` —\n * so `projectDir` scopes the walk to the library actually being linted.\n *\n * Indirect/variable-built keys (`const key = \\`a.${x}\\`; t(key)`) are not matched — only template\n * literals written directly inside the call/attribute are.\n */\nexport const expandDynamicKeysInProgram = (\n program: ts.Program,\n checker: ts.TypeChecker,\n projectDir: string\n): Array<ExpandedDynamicKey> => {\n const resolvedProjectDir = path.resolve(projectDir).replace(/\\\\/g, \"/\");\n const projectDirPrefix = resolvedProjectDir.endsWith(\"/\") ? resolvedProjectDir : `${resolvedProjectDir}/`;\n\n const results: Array<ExpandedDynamicKey> = [];\n\n for (const sourceFile of program.getSourceFiles()) {\n if (!isScannableSourceFile(sourceFile, projectDirPrefix)) {\n continue;\n }\n\n for (const template of collectDirectTemplates(sourceFile)) {\n results.push(expandTemplate(template, checker));\n }\n }\n\n return results;\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-unused-translation-key.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/no-unused-translation-key/no-unused-translation-key.ts"],"names":[],"mappings":";;;;AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,oDAAiE;AACjE,mDAA6B;AAC7B,uDAAyD;AACzD,iDAAmG;AAEnG,MAAM,UAAU,GAAG,mBAAW,CAAC,WAAW,CACxC,IAAI,CAAC,EAAE,CAAC,6FAA6F,IAAI,IAAI,IAAI,KAAK,CACvH,CAAC;AAKF,MAAM,uBAAuB,GAAG,8BAA8B,CAAC;AAmC/D,MAAM,UAAU,GAAG,CAAC,GAAwB,EAAU,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AAExH;;;;;GAKG;AACH,MAAM,eAAe,GAAG,CAAC,QAAsB,EAAoB,EAAE;IACnE,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC;IAC5C,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IAC3C,MAAM,eAAe,GAAG,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IAE/C,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC;AAEW,QAAA,sBAAsB,GAAG,UAAU,CAAsB;IACpE,IAAI,EAAE,2BAA2B;IACjC,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,cAAc,EAAE,IAAI;QACpB,IAAI,EAAE;YACJ,WAAW,EACT,wHAAwH;SAC3H;QACD,QAAQ,EAAE;YACR,SAAS,EAAE,0FAA0F;YACrG,eAAe,EAAE,mCAAmC;SACrD;QACD,MAAM,EAAE,EAAE;KACX;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC;YAChD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,eAAe,GAAG,IAAA,4BAAe,EAAC,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAC1E,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,gGAAgG;QAChG,IAAI,WAAoC,CAAC;QACzC,MAAM,OAAO,GAAG,GAAgB,EAAE;YAChC,WAAW,KAAX,WAAW,GAAK,IAAA,wCAAyB,EAAC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,EAAC;YACzE,OAAO,WAAW,CAAC;QACrB,CAAC,CAAC;QAEF,OAAO;YACL,YAAY,EAAE,CAAC,QAAsB,EAAE,EAAE;gBACvC,gFAAgF;gBAChF,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,yBAAyB,EAAE,CAAC;oBAC9D,OAAO;gBACT,CAAC;gBAED,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBACrC,IAAI,IAAA,mCAAoB,EAAC,OAAO,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;oBACzC,OAAO;gBACT,CAAC;gBAED,OAAO,CAAC,MAAM,CAAC;oBACb,SAAS,EAAE,WAAW;oBACtB,IAAI,EAAE,EAAE,GAAG,EAAE;oBACb,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG;oBACrB,OAAO,EAAE;wBACP;4BACE,SAAS,EAAE,iBAAiB;4BAC5B,IAAI,EAAE,EAAE,GAAG,EAAE;4BACb,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;yBAC3D;qBACF;iBACF,CAAC,CAAC;YACL,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["/**\n * ESLint rule that reports translation keys defined in a library's\n * `locales/en/translation.json` that are never referenced anywhere in that\n * library's source.\n *\n * Each library owns its own namespaced translations (see docs/tech/I18N.md), so\n * a key is considered used when it appears quoted anywhere in the owning\n * library's `.ts`/`.tsx` files (\"conservative-anywhere\" matching). Keys reached\n * through a dynamic template (`` t(`prefix.${x}`) ``) are kept via the static\n * text bookending the interpolation, and i18next plural forms are kept whenever\n * their base key is referenced. A dynamic template keeps every key under its\n * prefix, so keys behind one cannot be reported until the call site uses a\n * static key — what the companion `no-dynamic-translation-key` rule asks for.\n *\n * Matching is a heuristic over source text: this rule has no autofix, so a key\n * it reports is still a candidate for review before applying the removal\n * suggestion.\n *\n * Runs only on `**\\/locales/en/translation.json` — the English file is the\n * source of truth; other languages are managed by Crowdin.\n */\nimport { ESLintUtils, TSESTree } from \"@typescript-eslint/utils\";\nimport * as path from \"path\";\nimport { findNearestFile } from \"../../utils/file-utils\";\nimport { getUsedTranslationStrings, isTranslationKeyUsed, type UsedStrings } from \"./used-strings\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}/${name}.ts`\n);\n\ntype MessageIds = \"unusedKey\" | \"removeUnusedKey\";\ntype Options = [];\n\nconst TRANSLATION_FILE_SUFFIX = \"/locales/en/translation.json\";\n\n/**\n * The slice of `jsonc-eslint-parser`'s AST this rule visits. Declared here\n * because the parser ships ESM-only declarations (`lib/index.d.mts`) whose named\n * type exports are invisible to this CommonJS-compiled package — importing\n * anything from it fails with \"has no exported member\". The shapes are covered\n * end-to-end by the specs, which run the real parser.\n */\ninterface JsonNode {\n readonly range: readonly [number, number];\n}\n\ninterface JsonIdentifierKey {\n readonly type: \"JSONIdentifier\";\n readonly name: string;\n readonly loc: TSESTree.SourceLocation;\n}\n\ninterface JsonLiteralKey {\n readonly type: \"JSONLiteral\";\n readonly value: string | number | boolean | null;\n readonly loc: TSESTree.SourceLocation;\n}\n\ninterface JsonObjectExpression extends JsonNode {\n readonly properties: ReadonlyArray<JsonProperty>;\n readonly parent: { readonly type: string };\n}\n\ninterface JsonProperty extends JsonNode {\n readonly key: JsonIdentifierKey | JsonLiteralKey;\n readonly parent: JsonObjectExpression;\n}\n\nconst getKeyText = (key: JsonProperty[\"key\"]): string => (key.type === \"JSONIdentifier\" ? key.name : String(key.value));\n\n/**\n * The source range to drop so the remaining object stays valid JSON: a property\n * with a following sibling reaches up to that sibling (taking its own separating\n * comma and indentation with it), a trailing property reaches back to the end of\n * the preceding one, and a sole property leaves an empty object behind.\n */\nconst getRemovalRange = (property: JsonProperty): [number, number] => {\n const siblings = property.parent.properties;\n const position = siblings.indexOf(property);\n const nextSibling = siblings[position + 1];\n const previousSibling = siblings[position - 1];\n\n if (nextSibling) {\n return [property.range[0], nextSibling.range[0]];\n }\n if (previousSibling) {\n return [previousSibling.range[1], property.range[1]];\n }\n\n return [property.parent.range[0] + 1, property.parent.range[1] - 1];\n};\n\nexport const noUnusedTranslationKey = createRule<Options, MessageIds>({\n name: \"no-unused-translation-key\",\n meta: {\n type: \"suggestion\",\n hasSuggestions: true,\n docs: {\n description:\n \"Report translation keys in a library's locales/en/translation.json that are never referenced in that library's source.\",\n },\n messages: {\n unusedKey: 'Translation key \"{{key}}\" is not referenced anywhere in this library and can be removed.',\n removeUnusedKey: 'Remove translation key \"{{key}}\".',\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const filePath = context.filename.replace(/\\\\/g, \"/\");\n if (!filePath.endsWith(TRANSLATION_FILE_SUFFIX)) {\n return {};\n }\n\n const projectJsonPath = findNearestFile(context.filename, \"project.json\");\n if (!projectJsonPath) {\n return {};\n }\n\n // Scanning the whole library is expensive, so only pay for it once a key is actually inspected.\n let usedStrings: UsedStrings | undefined;\n const getUsed = (): UsedStrings => {\n usedStrings ??= getUsedTranslationStrings(path.dirname(projectJsonPath));\n return usedStrings;\n };\n\n return {\n JSONProperty: (property: JsonProperty) => {\n // Translation files are flat; anything nested belongs to a value, not to a key.\n if (property.parent.parent.type !== \"JSONExpressionStatement\") {\n return;\n }\n\n const key = getKeyText(property.key);\n if (isTranslationKeyUsed(getUsed(), key)) {\n return;\n }\n\n context.report({\n messageId: \"unusedKey\",\n data: { key },\n loc: property.key.loc,\n suggest: [\n {\n messageId: \"removeUnusedKey\",\n data: { key },\n fix: fixer => fixer.removeRange(getRemovalRange(property)),\n },\n ],\n });\n },\n };\n },\n});\n"]}