@principal-ai/quality-lens-registry 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -26,18 +26,24 @@ __export(index_exports, {
26
26
  areLensesAlternatives: () => areLensesAlternatives,
27
27
  detectLanguageFromExtension: () => detectLanguageFromExtension,
28
28
  findCategoryConflicts: () => findCategoryConflicts,
29
+ getAllColorModeConfigs: () => getAllColorModeConfigs,
29
30
  getAlternatives: () => getAlternatives,
31
+ getAvailableColorModes: () => getAvailableColorModes,
32
+ getAvailableColorModesFromLenses: () => getAvailableColorModesFromLenses,
30
33
  getCategoryConfig: () => getCategoryConfig,
31
34
  getCategoryDisplayName: () => getCategoryDisplayName,
32
35
  getCategoryForHexagonMetric: () => getCategoryForHexagonMetric,
33
36
  getCategoryForLens: () => getCategoryForLens,
37
+ getColorModeConfig: () => getColorModeConfig,
34
38
  getColorModeForCategory: () => getColorModeForCategory,
35
39
  getColorModeForHexagonMetric: () => getColorModeForHexagonMetric,
40
+ getColorModesForLanguage: () => getColorModesForLanguage,
36
41
  getHexagonMetricForCategory: () => getHexagonMetricForCategory,
37
42
  getHexagonMetricKeys: () => getHexagonMetricKeys,
38
43
  getLanguageConfig: () => getLanguageConfig,
39
44
  getLanguagesForCategory: () => getLanguagesForCategory,
40
45
  getLensById: () => getLensById,
46
+ getLensColorModes: () => getLensColorModes,
41
47
  getLensColorScheme: () => getLensColorScheme,
42
48
  getLensDisplayName: () => getLensDisplayName,
43
49
  getLensesByCategory: () => getLensesByCategory,
@@ -46,8 +52,11 @@ __export(index_exports, {
46
52
  getLensesWithAggregates: () => getLensesWithAggregates,
47
53
  getLensesWithFileMetrics: () => getLensesWithFileMetrics,
48
54
  isCategoryInverted: () => isCategoryInverted,
55
+ isColorModeAvailable: () => isColorModeAvailable,
49
56
  isHexagonMetricConfigured: () => isHexagonMetricConfigured,
57
+ isLensColorMode: () => isLensColorMode,
50
58
  isLensInHexagonMetric: () => isLensInHexagonMetric,
59
+ isValidColorMode: () => isValidColorMode,
51
60
  isValidLensId: () => isValidLensId,
52
61
  validateLensOutputs: () => validateLensOutputs
53
62
  });
@@ -696,6 +705,93 @@ function validateLensOutputs(lensesRan, fileMetricsProduced, aggregatesProduced)
696
705
  }
697
706
  return issues;
698
707
  }
708
+ var BUILT_IN_COLOR_MODES = [
709
+ {
710
+ id: "fileTypes",
711
+ name: "File Types",
712
+ description: "Color by file extension/type",
713
+ icon: "FileCode",
714
+ colorScheme: "categorical",
715
+ isBuiltIn: true
716
+ },
717
+ {
718
+ id: "git",
719
+ name: "Git Status",
720
+ description: "Color by git status (modified, added, etc.)",
721
+ icon: "GitBranch",
722
+ colorScheme: "categorical",
723
+ isBuiltIn: true
724
+ }
725
+ ];
726
+ function getAvailableColorModes() {
727
+ const builtIn = ["fileTypes", "git"];
728
+ const lensColorModes = getLensColorModes();
729
+ return [...builtIn, ...lensColorModes];
730
+ }
731
+ function getLensColorModes() {
732
+ return LENS_REGISTRY.filter((lens) => lens.outputsFileMetrics).map((lens) => lens.id);
733
+ }
734
+ function isValidColorMode(mode) {
735
+ return getAvailableColorModes().includes(mode);
736
+ }
737
+ function isLensColorMode(mode) {
738
+ return getLensColorModes().includes(mode);
739
+ }
740
+ function getColorModeConfig(mode) {
741
+ const builtIn = BUILT_IN_COLOR_MODES.find((m) => m.id === mode);
742
+ if (builtIn) return builtIn;
743
+ const lens = getLensById(mode);
744
+ if (lens && lens.outputsFileMetrics) {
745
+ const category = getCategoryConfig(lens.category);
746
+ return {
747
+ id: mode,
748
+ name: lens.name,
749
+ description: lens.description ?? `${lens.name} analysis`,
750
+ icon: category?.icon,
751
+ colorScheme: lens.colorScheme,
752
+ isBuiltIn: false,
753
+ category: lens.category
754
+ };
755
+ }
756
+ return void 0;
757
+ }
758
+ function getAllColorModeConfigs() {
759
+ const configs = [...BUILT_IN_COLOR_MODES];
760
+ for (const lens of LENS_REGISTRY) {
761
+ if (lens.outputsFileMetrics) {
762
+ const category = getCategoryConfig(lens.category);
763
+ configs.push({
764
+ id: lens.id,
765
+ name: lens.name,
766
+ description: lens.description ?? `${lens.name} analysis`,
767
+ icon: category?.icon,
768
+ colorScheme: lens.colorScheme,
769
+ isBuiltIn: false,
770
+ category: lens.category
771
+ });
772
+ }
773
+ }
774
+ return configs;
775
+ }
776
+ function getColorModesForLanguage(language) {
777
+ const builtIn = ["fileTypes", "git"];
778
+ const lensColorModes = LENS_REGISTRY.filter((lens) => lens.outputsFileMetrics && lens.languages.includes(language)).map((lens) => lens.id);
779
+ return [...builtIn, ...lensColorModes];
780
+ }
781
+ function getAvailableColorModesFromLenses(lensesRan) {
782
+ const builtIn = ["fileTypes", "git"];
783
+ const lensColorModes = lensesRan.filter((lensId) => {
784
+ const lens = getLensById(lensId);
785
+ return lens?.outputsFileMetrics;
786
+ });
787
+ return [...builtIn, ...lensColorModes];
788
+ }
789
+ function isColorModeAvailable(mode, lensesRan) {
790
+ if (mode === "fileTypes" || mode === "git") {
791
+ return true;
792
+ }
793
+ return lensesRan.includes(mode);
794
+ }
699
795
  // Annotate the CommonJS export names for ESM import in node:
700
796
  0 && (module.exports = {
701
797
  CATEGORY_CONFIGS,
@@ -704,18 +800,24 @@ function validateLensOutputs(lensesRan, fileMetricsProduced, aggregatesProduced)
704
800
  areLensesAlternatives,
705
801
  detectLanguageFromExtension,
706
802
  findCategoryConflicts,
803
+ getAllColorModeConfigs,
707
804
  getAlternatives,
805
+ getAvailableColorModes,
806
+ getAvailableColorModesFromLenses,
708
807
  getCategoryConfig,
709
808
  getCategoryDisplayName,
710
809
  getCategoryForHexagonMetric,
711
810
  getCategoryForLens,
811
+ getColorModeConfig,
712
812
  getColorModeForCategory,
713
813
  getColorModeForHexagonMetric,
814
+ getColorModesForLanguage,
714
815
  getHexagonMetricForCategory,
715
816
  getHexagonMetricKeys,
716
817
  getLanguageConfig,
717
818
  getLanguagesForCategory,
718
819
  getLensById,
820
+ getLensColorModes,
719
821
  getLensColorScheme,
720
822
  getLensDisplayName,
721
823
  getLensesByCategory,
@@ -724,8 +826,11 @@ function validateLensOutputs(lensesRan, fileMetricsProduced, aggregatesProduced)
724
826
  getLensesWithAggregates,
725
827
  getLensesWithFileMetrics,
726
828
  isCategoryInverted,
829
+ isColorModeAvailable,
727
830
  isHexagonMetricConfigured,
831
+ isLensColorMode,
728
832
  isLensInHexagonMetric,
833
+ isValidColorMode,
729
834
  isValidLensId,
730
835
  validateLensOutputs
731
836
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/registry.ts","../src/helpers.ts"],"sourcesContent":["/**\n * @principal-ai/quality-lens-registry\n *\n * Centralized registry of quality lens metadata for the Principal AI quality toolchain.\n *\n * This package provides a single source of truth for:\n * - Lens metadata (what lenses exist, what they do)\n * - Category definitions (linting, formatting, types, etc.)\n * - Language support (which lenses work with which languages)\n * - Helper functions for lookups and validation\n *\n * When adding a new lens:\n * 1. Add it to LENS_REGISTRY in src/registry.ts\n * 2. Implement the lens in @principal-ai/codebase-quality-lenses\n * 3. The UI packages will automatically discover and support it\n *\n * @example\n * ```typescript\n * import {\n * getLensById,\n * getLensesByCategory,\n * getColorModeForCategory,\n * LENS_REGISTRY\n * } from '@principal-ai/quality-lens-registry';\n *\n * // Get metadata for a specific lens\n * const eslint = getLensById('eslint');\n *\n * // Get all linting tools\n * const linters = getLensesByCategory('linting');\n *\n * // Determine which color mode to use based on lenses that ran\n * const colorMode = getColorModeForCategory('linting', ['biome-lint', 'typescript']);\n * // Returns 'biome-lint'\n * ```\n */\n\n// Export types\nexport type {\n Language,\n LensCategory,\n ColorScheme,\n LensMetadata,\n CategoryConfig,\n LanguageConfig,\n} from './types.js';\n\n// Export registry data\nexport {\n LENS_REGISTRY,\n CATEGORY_CONFIGS,\n LANGUAGE_CONFIGS,\n} from './registry.js';\n\n// Export helper functions\nexport {\n // Lens lookups\n getLensById,\n getLensesByCategory,\n getLensesByLanguage,\n getLensesByCategoryAndLanguage,\n getCategoryForLens,\n getAlternatives,\n areLensesAlternatives,\n getLensesWithFileMetrics,\n getLensesWithAggregates,\n\n // Color mode helpers\n getColorModeForCategory,\n getLensDisplayName,\n getLensColorScheme,\n\n // Category helpers\n getCategoryConfig,\n getCategoryDisplayName,\n isCategoryInverted,\n\n // Language helpers\n getLanguageConfig,\n detectLanguageFromExtension,\n getLanguagesForCategory,\n\n // Hexagon metric helpers\n type HexagonMetricKey,\n getCategoryForHexagonMetric,\n getHexagonMetricForCategory,\n isLensInHexagonMetric,\n getColorModeForHexagonMetric,\n isHexagonMetricConfigured,\n getHexagonMetricKeys,\n\n // Validation helpers\n isValidLensId,\n findCategoryConflicts,\n validateLensOutputs,\n} from './helpers.js';\n","import type { LensMetadata, CategoryConfig, LanguageConfig } from './types.js';\n\n/**\n * Central registry of all quality lenses\n *\n * When adding a new lens:\n * 1. Add it to this registry with complete metadata\n * 2. Implement the lens in @principal-ai/codebase-quality-lenses\n * 3. The UI packages will automatically discover and support it\n */\nexport const LENS_REGISTRY: LensMetadata[] = [\n // ============================================================\n // LINTING - Code style and bug detection\n // ============================================================\n\n // TypeScript/JavaScript linting\n {\n id: 'eslint',\n name: 'ESLint',\n category: 'linting',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Pluggable linting utility for JavaScript and TypeScript',\n command: 'eslint',\n },\n {\n id: 'biome-lint',\n name: 'Biome Lint',\n category: 'linting',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['eslint'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Fast linter for JavaScript and TypeScript',\n command: 'biome lint',\n },\n {\n id: 'oxlint',\n name: 'OxLint',\n category: 'linting',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['eslint', 'biome-lint'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Blazing fast JavaScript/TypeScript linter',\n command: 'oxlint',\n },\n\n // Python linting\n {\n id: 'ruff',\n name: 'Ruff',\n category: 'linting',\n languages: ['python'],\n alternativeTo: ['pylint', 'flake8'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Extremely fast Python linter',\n command: 'ruff check',\n },\n {\n id: 'pylint',\n name: 'Pylint',\n category: 'linting',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Python static code analyzer',\n command: 'pylint',\n },\n\n // Go linting\n {\n id: 'golangci-lint',\n name: 'golangci-lint',\n category: 'linting',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Fast linters runner for Go',\n command: 'golangci-lint run',\n },\n\n // Rust linting\n {\n id: 'clippy',\n name: 'Clippy',\n category: 'linting',\n languages: ['rust'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Rust linter',\n command: 'cargo clippy',\n },\n\n // ============================================================\n // FORMATTING - Code formatting\n // ============================================================\n\n // TypeScript/JavaScript formatting\n {\n id: 'prettier',\n name: 'Prettier',\n category: 'formatting',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Opinionated code formatter',\n command: 'prettier --check',\n },\n {\n id: 'biome-format',\n name: 'Biome Format',\n category: 'formatting',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['prettier'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Fast code formatter for JavaScript and TypeScript',\n command: 'biome format',\n },\n\n // Python formatting\n {\n id: 'black',\n name: 'Black',\n category: 'formatting',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'The uncompromising Python code formatter',\n command: 'black --check',\n },\n {\n id: 'ruff-format',\n name: 'Ruff Format',\n category: 'formatting',\n languages: ['python'],\n alternativeTo: ['black'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Fast Python formatter (Ruff)',\n command: 'ruff format --check',\n },\n\n // Go formatting\n {\n id: 'gofmt',\n name: 'gofmt',\n category: 'formatting',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Go code formatter',\n command: 'gofmt -l',\n },\n\n // Rust formatting\n {\n id: 'rustfmt',\n name: 'rustfmt',\n category: 'formatting',\n languages: ['rust'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Rust code formatter',\n command: 'cargo fmt --check',\n },\n\n // ============================================================\n // TYPES - Type checking\n // ============================================================\n\n // TypeScript\n {\n id: 'typescript',\n name: 'TypeScript',\n category: 'types',\n languages: ['typescript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'TypeScript type checker',\n command: 'tsc --noEmit',\n },\n\n // Python type checking\n {\n id: 'mypy',\n name: 'MyPy',\n category: 'types',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Static type checker for Python',\n command: 'mypy',\n },\n {\n id: 'pyright',\n name: 'Pyright',\n category: 'types',\n languages: ['python'],\n alternativeTo: ['mypy'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Static type checker for Python',\n command: 'pyright',\n },\n\n // Go type checking (built into compiler)\n {\n id: 'go-vet',\n name: 'Go Vet',\n category: 'types',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Go static analyzer',\n command: 'go vet',\n },\n\n // ============================================================\n // TESTS - Test coverage and results\n // ============================================================\n\n // JavaScript/TypeScript testing\n {\n id: 'jest',\n name: 'Jest',\n category: 'tests',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'JavaScript testing framework',\n command: 'jest --coverage',\n },\n {\n id: 'vitest',\n name: 'Vitest',\n category: 'tests',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['jest'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Vite-native testing framework',\n command: 'vitest run --coverage',\n },\n {\n id: 'bun-test',\n name: 'Bun Test',\n category: 'tests',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['jest', 'vitest'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Bun native test runner',\n command: 'bun test',\n },\n\n // Python testing\n {\n id: 'pytest',\n name: 'Pytest',\n category: 'tests',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Python testing framework',\n command: 'pytest --cov',\n },\n\n // Go testing\n {\n id: 'go-test',\n name: 'Go Test',\n category: 'tests',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Go test runner',\n command: 'go test -cover',\n },\n\n // Rust testing\n {\n id: 'cargo-test',\n name: 'Cargo Test',\n category: 'tests',\n languages: ['rust'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Rust test runner',\n command: 'cargo test',\n },\n\n // ============================================================\n // DEAD CODE - Unused code detection\n // ============================================================\n\n // TypeScript/JavaScript\n {\n id: 'knip',\n name: 'Knip',\n category: 'dead-code',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Find unused files, dependencies and exports',\n command: 'knip',\n },\n\n // Python\n {\n id: 'vulture',\n name: 'Vulture',\n category: 'dead-code',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Find dead Python code',\n command: 'vulture',\n },\n\n // ============================================================\n // DOCUMENTATION - Documentation coverage\n // ============================================================\n\n {\n id: 'alexandria',\n name: 'Alexandria',\n category: 'documentation',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Documentation coverage checker',\n command: 'alexandria lint',\n },\n {\n id: 'typedoc',\n name: 'TypeDoc',\n category: 'documentation',\n languages: ['typescript'],\n outputsFileMetrics: false,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'TypeScript documentation generator',\n command: 'typedoc',\n },\n\n // ============================================================\n // SECURITY - Security scanning\n // ============================================================\n\n {\n id: 'npm-audit',\n name: 'npm audit',\n category: 'security',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: false,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Check for known vulnerabilities in dependencies',\n command: 'npm audit',\n },\n {\n id: 'bandit',\n name: 'Bandit',\n category: 'security',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Python security linter',\n command: 'bandit -r',\n },\n];\n\n/**\n * Category configurations for UI display\n */\nexport const CATEGORY_CONFIGS: CategoryConfig[] = [\n {\n id: 'linting',\n name: 'Linting',\n description: 'Code style and bug detection',\n icon: 'AlertCircle',\n },\n {\n id: 'formatting',\n name: 'Formatting',\n description: 'Code formatting consistency',\n icon: 'AlignLeft',\n },\n {\n id: 'types',\n name: 'Types',\n description: 'Type safety and checking',\n icon: 'FileType',\n },\n {\n id: 'tests',\n name: 'Tests',\n description: 'Test coverage and results',\n icon: 'TestTube',\n },\n {\n id: 'dead-code',\n name: 'Dead Code',\n description: 'Unused code detection',\n icon: 'Trash2',\n invertedScale: true,\n },\n {\n id: 'documentation',\n name: 'Documentation',\n description: 'Documentation coverage',\n icon: 'FileText',\n },\n {\n id: 'security',\n name: 'Security',\n description: 'Security vulnerability scanning',\n icon: 'Shield',\n },\n {\n id: 'complexity',\n name: 'Complexity',\n description: 'Code complexity metrics',\n icon: 'GitBranch',\n },\n];\n\n/**\n * Language configurations for UI display\n */\nexport const LANGUAGE_CONFIGS: LanguageConfig[] = [\n {\n id: 'typescript',\n name: 'TypeScript',\n extensions: ['.ts', '.tsx', '.mts', '.cts'],\n icon: 'TS',\n },\n {\n id: 'javascript',\n name: 'JavaScript',\n extensions: ['.js', '.jsx', '.mjs', '.cjs'],\n icon: 'JS',\n },\n {\n id: 'python',\n name: 'Python',\n extensions: ['.py', '.pyi'],\n icon: 'PY',\n },\n {\n id: 'go',\n name: 'Go',\n extensions: ['.go'],\n icon: 'GO',\n },\n {\n id: 'rust',\n name: 'Rust',\n extensions: ['.rs'],\n icon: 'RS',\n },\n {\n id: 'java',\n name: 'Java',\n extensions: ['.java'],\n icon: 'JV',\n },\n {\n id: 'csharp',\n name: 'C#',\n extensions: ['.cs'],\n icon: 'C#',\n },\n {\n id: 'ruby',\n name: 'Ruby',\n extensions: ['.rb'],\n icon: 'RB',\n },\n {\n id: 'php',\n name: 'PHP',\n extensions: ['.php'],\n icon: 'PHP',\n },\n];\n","import type { LensMetadata, LensCategory, Language, CategoryConfig, LanguageConfig } from './types.js';\nimport { LENS_REGISTRY, CATEGORY_CONFIGS, LANGUAGE_CONFIGS } from './registry.js';\n\n// ============================================================\n// Lens Lookups\n// ============================================================\n\n/**\n * Get lens metadata by ID\n */\nexport function getLensById(id: string): LensMetadata | undefined {\n return LENS_REGISTRY.find((lens) => lens.id === id);\n}\n\n/**\n * Get all lenses in a category\n */\nexport function getLensesByCategory(category: LensCategory): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.category === category);\n}\n\n/**\n * Get all lenses that support a language\n */\nexport function getLensesByLanguage(language: Language): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.languages.includes(language));\n}\n\n/**\n * Get lenses that support a category for a specific language\n */\nexport function getLensesByCategoryAndLanguage(\n category: LensCategory,\n language: Language\n): LensMetadata[] {\n return LENS_REGISTRY.filter(\n (lens) => lens.category === category && lens.languages.includes(language)\n );\n}\n\n/**\n * Get the category for a lens ID\n */\nexport function getCategoryForLens(lensId: string): LensCategory | undefined {\n return getLensById(lensId)?.category;\n}\n\n/**\n * Get alternative lenses for a given lens ID\n */\nexport function getAlternatives(lensId: string): LensMetadata[] {\n const lens = getLensById(lensId);\n if (!lens) return [];\n\n // Find lenses that list this one as an alternative\n const listedAsAlternative = LENS_REGISTRY.filter(\n (other) => other.alternativeTo?.includes(lensId)\n );\n\n // Find lenses that this one lists as alternatives\n const thisListsAsAlternative = lens.alternativeTo\n ? LENS_REGISTRY.filter((other) => lens.alternativeTo!.includes(other.id))\n : [];\n\n // Combine and dedupe\n const all = [...listedAsAlternative, ...thisListsAsAlternative];\n return Array.from(new Map(all.map((l) => [l.id, l])).values());\n}\n\n/**\n * Check if two lenses are alternatives to each other\n */\nexport function areLensesAlternatives(lensId1: string, lensId2: string): boolean {\n const lens1 = getLensById(lensId1);\n const lens2 = getLensById(lensId2);\n\n if (!lens1 || !lens2) return false;\n if (lens1.category !== lens2.category) return false;\n\n return (\n lens1.alternativeTo?.includes(lensId2) ||\n lens2.alternativeTo?.includes(lensId1) ||\n false\n );\n}\n\n/**\n * Get all lenses that output file metrics (for File City visualization)\n */\nexport function getLensesWithFileMetrics(): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.outputsFileMetrics);\n}\n\n/**\n * Get all lenses that output aggregate scores (for Quality Hexagon)\n */\nexport function getLensesWithAggregates(): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.outputsAggregate);\n}\n\n// ============================================================\n// Color Mode Helpers (for File City)\n// ============================================================\n\n/**\n * Get the appropriate color mode (lens ID) for a category based on which lenses ran\n * Returns the first lens that ran for the category, preferring alternatives in order\n */\nexport function getColorModeForCategory(\n category: LensCategory,\n lensesRan: string[]\n): string | null {\n const lensesInCategory = getLensesByCategory(category);\n\n // Find the first lens that ran\n for (const lensId of lensesRan) {\n if (lensesInCategory.some((lens) => lens.id === lensId)) {\n return lensId;\n }\n }\n\n return null;\n}\n\n/**\n * Get display name for a lens (for UI labels)\n */\nexport function getLensDisplayName(lensId: string): string {\n return getLensById(lensId)?.name ?? lensId;\n}\n\n/**\n * Get color scheme for a lens (for File City layer rendering)\n */\nexport function getLensColorScheme(lensId: string): 'issues' | 'coverage' | 'binary' {\n return getLensById(lensId)?.colorScheme ?? 'issues';\n}\n\n// ============================================================\n// Category Helpers\n// ============================================================\n\n/**\n * Get category configuration\n */\nexport function getCategoryConfig(category: LensCategory): CategoryConfig | undefined {\n return CATEGORY_CONFIGS.find((c) => c.id === category);\n}\n\n/**\n * Get category display name\n */\nexport function getCategoryDisplayName(category: LensCategory): string {\n return getCategoryConfig(category)?.name ?? category;\n}\n\n/**\n * Check if a category uses inverted scale (lower is better)\n */\nexport function isCategoryInverted(category: LensCategory): boolean {\n return getCategoryConfig(category)?.invertedScale ?? false;\n}\n\n// ============================================================\n// Language Helpers\n// ============================================================\n\n/**\n * Get language configuration\n */\nexport function getLanguageConfig(language: Language): LanguageConfig | undefined {\n return LANGUAGE_CONFIGS.find((l) => l.id === language);\n}\n\n/**\n * Detect language from file extension\n */\nexport function detectLanguageFromExtension(extension: string): Language | undefined {\n const normalizedExt = extension.startsWith('.') ? extension : `.${extension}`;\n const config = LANGUAGE_CONFIGS.find((l) =>\n l.extensions.includes(normalizedExt.toLowerCase())\n );\n return config?.id;\n}\n\n/**\n * Get all languages that have lenses in a category\n */\nexport function getLanguagesForCategory(category: LensCategory): Language[] {\n const lenses = getLensesByCategory(category);\n const languages = new Set<Language>();\n for (const lens of lenses) {\n for (const lang of lens.languages) {\n languages.add(lang);\n }\n }\n return Array.from(languages);\n}\n\n// ============================================================\n// Hexagon Metric Helpers (for Quality Hexagon UI)\n// ============================================================\n\n/**\n * Hexagon metric keys use camelCase (from QualityMetrics interface)\n * These map to LensCategory which uses kebab-case\n */\nexport type HexagonMetricKey =\n | 'linting'\n | 'formatting'\n | 'types'\n | 'tests'\n | 'deadCode'\n | 'documentation';\n\n/**\n * Map hexagon metric keys to registry LensCategory\n */\nconst HEXAGON_METRIC_TO_CATEGORY: Record<HexagonMetricKey, LensCategory> = {\n linting: 'linting',\n formatting: 'formatting',\n types: 'types',\n tests: 'tests',\n deadCode: 'dead-code',\n documentation: 'documentation',\n};\n\n/**\n * Map LensCategory back to hexagon metric keys\n */\nconst CATEGORY_TO_HEXAGON_METRIC: Partial<Record<LensCategory, HexagonMetricKey>> = {\n 'linting': 'linting',\n 'formatting': 'formatting',\n 'types': 'types',\n 'tests': 'tests',\n 'dead-code': 'deadCode',\n 'documentation': 'documentation',\n};\n\n/**\n * Get the LensCategory for a hexagon metric key\n */\nexport function getCategoryForHexagonMetric(metric: HexagonMetricKey): LensCategory {\n return HEXAGON_METRIC_TO_CATEGORY[metric];\n}\n\n/**\n * Get the hexagon metric key for a LensCategory\n */\nexport function getHexagonMetricForCategory(category: LensCategory): HexagonMetricKey | undefined {\n return CATEGORY_TO_HEXAGON_METRIC[category];\n}\n\n/**\n * Check if a lens ID belongs to a hexagon metric\n */\nexport function isLensInHexagonMetric(lensId: string, metric: HexagonMetricKey): boolean {\n const lensCategory = getCategoryForLens(lensId);\n if (!lensCategory) return false;\n return HEXAGON_METRIC_TO_CATEGORY[metric] === lensCategory;\n}\n\n/**\n * Get the color mode for a hexagon metric based on which lenses ran.\n * This is the main entry point for the QualityHexagon panel.\n */\nexport function getColorModeForHexagonMetric(\n metric: HexagonMetricKey,\n lensesRan: string[]\n): string | null {\n const category = HEXAGON_METRIC_TO_CATEGORY[metric];\n return getColorModeForCategory(category, lensesRan);\n}\n\n/**\n * Check if a hexagon metric is configured (has at least one lens that ran)\n */\nexport function isHexagonMetricConfigured(\n metric: HexagonMetricKey,\n lensesRan: string[] | undefined\n): boolean {\n // undefined = old data without lensesRan tracking, assume all configured (backwards compatibility)\n if (lensesRan === undefined) {\n return true;\n }\n // Empty array = new data, explicitly no lenses ran for this package\n if (lensesRan.length === 0) {\n return false;\n }\n return lensesRan.some((lensId) => isLensInHexagonMetric(lensId, metric));\n}\n\n/**\n * Get all hexagon metric keys\n */\nexport function getHexagonMetricKeys(): HexagonMetricKey[] {\n return Object.keys(HEXAGON_METRIC_TO_CATEGORY) as HexagonMetricKey[];\n}\n\n// ============================================================\n// Validation Helpers\n// ============================================================\n\n/**\n * Validate that a lens ID exists in the registry\n */\nexport function isValidLensId(lensId: string): boolean {\n return getLensById(lensId) !== undefined;\n}\n\n/**\n * Find lenses that ran for the same category (potential conflicts)\n */\nexport function findCategoryConflicts(\n lensesRan: string[]\n): Array<{ category: LensCategory; lenses: string[] }> {\n const byCategory = new Map<LensCategory, string[]>();\n\n for (const lensId of lensesRan) {\n const category = getCategoryForLens(lensId);\n if (category) {\n const existing = byCategory.get(category) || [];\n existing.push(lensId);\n byCategory.set(category, existing);\n }\n }\n\n const conflicts: Array<{ category: LensCategory; lenses: string[] }> = [];\n for (const [category, lenses] of byCategory) {\n if (lenses.length > 1) {\n conflicts.push({ category, lenses });\n }\n }\n\n return conflicts;\n}\n\n/**\n * Check if all required lenses produced expected outputs\n */\nexport function validateLensOutputs(\n lensesRan: string[],\n fileMetricsProduced: string[],\n aggregatesProduced: string[]\n): Array<{ lensId: string; missing: ('fileMetrics' | 'aggregate')[] }> {\n const issues: Array<{ lensId: string; missing: ('fileMetrics' | 'aggregate')[] }> = [];\n\n for (const lensId of lensesRan) {\n const lens = getLensById(lensId);\n if (!lens) continue;\n\n const missing: ('fileMetrics' | 'aggregate')[] = [];\n\n if (lens.outputsFileMetrics && !fileMetricsProduced.includes(lensId)) {\n missing.push('fileMetrics');\n }\n if (lens.outputsAggregate && !aggregatesProduced.includes(lensId)) {\n missing.push('aggregate');\n }\n\n if (missing.length > 0) {\n issues.push({ lensId, missing });\n }\n }\n\n return issues;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/registry.ts","../src/helpers.ts"],"sourcesContent":["/**\n * @principal-ai/quality-lens-registry\n *\n * Centralized registry of quality lens metadata for the Principal AI quality toolchain.\n *\n * This package provides a single source of truth for:\n * - Lens metadata (what lenses exist, what they do)\n * - Category definitions (linting, formatting, types, etc.)\n * - Language support (which lenses work with which languages)\n * - Helper functions for lookups and validation\n *\n * When adding a new lens:\n * 1. Add it to LENS_REGISTRY in src/registry.ts\n * 2. Implement the lens in @principal-ai/codebase-quality-lenses\n * 3. The UI packages will automatically discover and support it\n *\n * @example\n * ```typescript\n * import {\n * getLensById,\n * getLensesByCategory,\n * getColorModeForCategory,\n * LENS_REGISTRY\n * } from '@principal-ai/quality-lens-registry';\n *\n * // Get metadata for a specific lens\n * const eslint = getLensById('eslint');\n *\n * // Get all linting tools\n * const linters = getLensesByCategory('linting');\n *\n * // Determine which color mode to use based on lenses that ran\n * const colorMode = getColorModeForCategory('linting', ['biome-lint', 'typescript']);\n * // Returns 'biome-lint'\n * ```\n */\n\n// Export types\nexport type {\n Language,\n LensCategory,\n ColorScheme,\n LensMetadata,\n CategoryConfig,\n LanguageConfig,\n // Color mode types\n BuiltInColorMode,\n LensColorMode,\n ColorMode,\n ColorModeConfig,\n} from './types.js';\n\n// Export registry data\nexport {\n LENS_REGISTRY,\n CATEGORY_CONFIGS,\n LANGUAGE_CONFIGS,\n} from './registry.js';\n\n// Export helper functions\nexport {\n // Lens lookups\n getLensById,\n getLensesByCategory,\n getLensesByLanguage,\n getLensesByCategoryAndLanguage,\n getCategoryForLens,\n getAlternatives,\n areLensesAlternatives,\n getLensesWithFileMetrics,\n getLensesWithAggregates,\n\n // Color mode helpers\n getColorModeForCategory,\n getLensDisplayName,\n getLensColorScheme,\n\n // Category helpers\n getCategoryConfig,\n getCategoryDisplayName,\n isCategoryInverted,\n\n // Language helpers\n getLanguageConfig,\n detectLanguageFromExtension,\n getLanguagesForCategory,\n\n // Hexagon metric helpers\n type HexagonMetricKey,\n getCategoryForHexagonMetric,\n getHexagonMetricForCategory,\n isLensInHexagonMetric,\n getColorModeForHexagonMetric,\n isHexagonMetricConfigured,\n getHexagonMetricKeys,\n\n // Validation helpers\n isValidLensId,\n findCategoryConflicts,\n validateLensOutputs,\n\n // Color mode helpers (for File City)\n getAvailableColorModes,\n getLensColorModes,\n isValidColorMode,\n isLensColorMode,\n getColorModeConfig,\n getAllColorModeConfigs,\n getColorModesForLanguage,\n getAvailableColorModesFromLenses,\n isColorModeAvailable,\n} from './helpers.js';\n","import type { LensMetadata, CategoryConfig, LanguageConfig } from './types.js';\n\n/**\n * Central registry of all quality lenses\n *\n * When adding a new lens:\n * 1. Add it to this registry with complete metadata\n * 2. Implement the lens in @principal-ai/codebase-quality-lenses\n * 3. The UI packages will automatically discover and support it\n */\nexport const LENS_REGISTRY: LensMetadata[] = [\n // ============================================================\n // LINTING - Code style and bug detection\n // ============================================================\n\n // TypeScript/JavaScript linting\n {\n id: 'eslint',\n name: 'ESLint',\n category: 'linting',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Pluggable linting utility for JavaScript and TypeScript',\n command: 'eslint',\n },\n {\n id: 'biome-lint',\n name: 'Biome Lint',\n category: 'linting',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['eslint'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Fast linter for JavaScript and TypeScript',\n command: 'biome lint',\n },\n {\n id: 'oxlint',\n name: 'OxLint',\n category: 'linting',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['eslint', 'biome-lint'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Blazing fast JavaScript/TypeScript linter',\n command: 'oxlint',\n },\n\n // Python linting\n {\n id: 'ruff',\n name: 'Ruff',\n category: 'linting',\n languages: ['python'],\n alternativeTo: ['pylint', 'flake8'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Extremely fast Python linter',\n command: 'ruff check',\n },\n {\n id: 'pylint',\n name: 'Pylint',\n category: 'linting',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Python static code analyzer',\n command: 'pylint',\n },\n\n // Go linting\n {\n id: 'golangci-lint',\n name: 'golangci-lint',\n category: 'linting',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Fast linters runner for Go',\n command: 'golangci-lint run',\n },\n\n // Rust linting\n {\n id: 'clippy',\n name: 'Clippy',\n category: 'linting',\n languages: ['rust'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Rust linter',\n command: 'cargo clippy',\n },\n\n // ============================================================\n // FORMATTING - Code formatting\n // ============================================================\n\n // TypeScript/JavaScript formatting\n {\n id: 'prettier',\n name: 'Prettier',\n category: 'formatting',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Opinionated code formatter',\n command: 'prettier --check',\n },\n {\n id: 'biome-format',\n name: 'Biome Format',\n category: 'formatting',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['prettier'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Fast code formatter for JavaScript and TypeScript',\n command: 'biome format',\n },\n\n // Python formatting\n {\n id: 'black',\n name: 'Black',\n category: 'formatting',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'The uncompromising Python code formatter',\n command: 'black --check',\n },\n {\n id: 'ruff-format',\n name: 'Ruff Format',\n category: 'formatting',\n languages: ['python'],\n alternativeTo: ['black'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Fast Python formatter (Ruff)',\n command: 'ruff format --check',\n },\n\n // Go formatting\n {\n id: 'gofmt',\n name: 'gofmt',\n category: 'formatting',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Go code formatter',\n command: 'gofmt -l',\n },\n\n // Rust formatting\n {\n id: 'rustfmt',\n name: 'rustfmt',\n category: 'formatting',\n languages: ['rust'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Rust code formatter',\n command: 'cargo fmt --check',\n },\n\n // ============================================================\n // TYPES - Type checking\n // ============================================================\n\n // TypeScript\n {\n id: 'typescript',\n name: 'TypeScript',\n category: 'types',\n languages: ['typescript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'TypeScript type checker',\n command: 'tsc --noEmit',\n },\n\n // Python type checking\n {\n id: 'mypy',\n name: 'MyPy',\n category: 'types',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Static type checker for Python',\n command: 'mypy',\n },\n {\n id: 'pyright',\n name: 'Pyright',\n category: 'types',\n languages: ['python'],\n alternativeTo: ['mypy'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Static type checker for Python',\n command: 'pyright',\n },\n\n // Go type checking (built into compiler)\n {\n id: 'go-vet',\n name: 'Go Vet',\n category: 'types',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Go static analyzer',\n command: 'go vet',\n },\n\n // ============================================================\n // TESTS - Test coverage and results\n // ============================================================\n\n // JavaScript/TypeScript testing\n {\n id: 'jest',\n name: 'Jest',\n category: 'tests',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'JavaScript testing framework',\n command: 'jest --coverage',\n },\n {\n id: 'vitest',\n name: 'Vitest',\n category: 'tests',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['jest'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Vite-native testing framework',\n command: 'vitest run --coverage',\n },\n {\n id: 'bun-test',\n name: 'Bun Test',\n category: 'tests',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['jest', 'vitest'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Bun native test runner',\n command: 'bun test',\n },\n\n // Python testing\n {\n id: 'pytest',\n name: 'Pytest',\n category: 'tests',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Python testing framework',\n command: 'pytest --cov',\n },\n\n // Go testing\n {\n id: 'go-test',\n name: 'Go Test',\n category: 'tests',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Go test runner',\n command: 'go test -cover',\n },\n\n // Rust testing\n {\n id: 'cargo-test',\n name: 'Cargo Test',\n category: 'tests',\n languages: ['rust'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Rust test runner',\n command: 'cargo test',\n },\n\n // ============================================================\n // DEAD CODE - Unused code detection\n // ============================================================\n\n // TypeScript/JavaScript\n {\n id: 'knip',\n name: 'Knip',\n category: 'dead-code',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Find unused files, dependencies and exports',\n command: 'knip',\n },\n\n // Python\n {\n id: 'vulture',\n name: 'Vulture',\n category: 'dead-code',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Find dead Python code',\n command: 'vulture',\n },\n\n // ============================================================\n // DOCUMENTATION - Documentation coverage\n // ============================================================\n\n {\n id: 'alexandria',\n name: 'Alexandria',\n category: 'documentation',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Documentation coverage checker',\n command: 'alexandria lint',\n },\n {\n id: 'typedoc',\n name: 'TypeDoc',\n category: 'documentation',\n languages: ['typescript'],\n outputsFileMetrics: false,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'TypeScript documentation generator',\n command: 'typedoc',\n },\n\n // ============================================================\n // SECURITY - Security scanning\n // ============================================================\n\n {\n id: 'npm-audit',\n name: 'npm audit',\n category: 'security',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: false,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Check for known vulnerabilities in dependencies',\n command: 'npm audit',\n },\n {\n id: 'bandit',\n name: 'Bandit',\n category: 'security',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Python security linter',\n command: 'bandit -r',\n },\n];\n\n/**\n * Category configurations for UI display\n */\nexport const CATEGORY_CONFIGS: CategoryConfig[] = [\n {\n id: 'linting',\n name: 'Linting',\n description: 'Code style and bug detection',\n icon: 'AlertCircle',\n },\n {\n id: 'formatting',\n name: 'Formatting',\n description: 'Code formatting consistency',\n icon: 'AlignLeft',\n },\n {\n id: 'types',\n name: 'Types',\n description: 'Type safety and checking',\n icon: 'FileType',\n },\n {\n id: 'tests',\n name: 'Tests',\n description: 'Test coverage and results',\n icon: 'TestTube',\n },\n {\n id: 'dead-code',\n name: 'Dead Code',\n description: 'Unused code detection',\n icon: 'Trash2',\n invertedScale: true,\n },\n {\n id: 'documentation',\n name: 'Documentation',\n description: 'Documentation coverage',\n icon: 'FileText',\n },\n {\n id: 'security',\n name: 'Security',\n description: 'Security vulnerability scanning',\n icon: 'Shield',\n },\n {\n id: 'complexity',\n name: 'Complexity',\n description: 'Code complexity metrics',\n icon: 'GitBranch',\n },\n];\n\n/**\n * Language configurations for UI display\n */\nexport const LANGUAGE_CONFIGS: LanguageConfig[] = [\n {\n id: 'typescript',\n name: 'TypeScript',\n extensions: ['.ts', '.tsx', '.mts', '.cts'],\n icon: 'TS',\n },\n {\n id: 'javascript',\n name: 'JavaScript',\n extensions: ['.js', '.jsx', '.mjs', '.cjs'],\n icon: 'JS',\n },\n {\n id: 'python',\n name: 'Python',\n extensions: ['.py', '.pyi'],\n icon: 'PY',\n },\n {\n id: 'go',\n name: 'Go',\n extensions: ['.go'],\n icon: 'GO',\n },\n {\n id: 'rust',\n name: 'Rust',\n extensions: ['.rs'],\n icon: 'RS',\n },\n {\n id: 'java',\n name: 'Java',\n extensions: ['.java'],\n icon: 'JV',\n },\n {\n id: 'csharp',\n name: 'C#',\n extensions: ['.cs'],\n icon: 'C#',\n },\n {\n id: 'ruby',\n name: 'Ruby',\n extensions: ['.rb'],\n icon: 'RB',\n },\n {\n id: 'php',\n name: 'PHP',\n extensions: ['.php'],\n icon: 'PHP',\n },\n];\n","import type { LensMetadata, LensCategory, Language, CategoryConfig, LanguageConfig, ColorMode, LensColorMode, ColorModeConfig, ColorScheme } from './types.js';\nimport { LENS_REGISTRY, CATEGORY_CONFIGS, LANGUAGE_CONFIGS } from './registry.js';\n\n// ============================================================\n// Lens Lookups\n// ============================================================\n\n/**\n * Get lens metadata by ID\n */\nexport function getLensById(id: string): LensMetadata | undefined {\n return LENS_REGISTRY.find((lens) => lens.id === id);\n}\n\n/**\n * Get all lenses in a category\n */\nexport function getLensesByCategory(category: LensCategory): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.category === category);\n}\n\n/**\n * Get all lenses that support a language\n */\nexport function getLensesByLanguage(language: Language): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.languages.includes(language));\n}\n\n/**\n * Get lenses that support a category for a specific language\n */\nexport function getLensesByCategoryAndLanguage(\n category: LensCategory,\n language: Language\n): LensMetadata[] {\n return LENS_REGISTRY.filter(\n (lens) => lens.category === category && lens.languages.includes(language)\n );\n}\n\n/**\n * Get the category for a lens ID\n */\nexport function getCategoryForLens(lensId: string): LensCategory | undefined {\n return getLensById(lensId)?.category;\n}\n\n/**\n * Get alternative lenses for a given lens ID\n */\nexport function getAlternatives(lensId: string): LensMetadata[] {\n const lens = getLensById(lensId);\n if (!lens) return [];\n\n // Find lenses that list this one as an alternative\n const listedAsAlternative = LENS_REGISTRY.filter(\n (other) => other.alternativeTo?.includes(lensId)\n );\n\n // Find lenses that this one lists as alternatives\n const thisListsAsAlternative = lens.alternativeTo\n ? LENS_REGISTRY.filter((other) => lens.alternativeTo!.includes(other.id))\n : [];\n\n // Combine and dedupe\n const all = [...listedAsAlternative, ...thisListsAsAlternative];\n return Array.from(new Map(all.map((l) => [l.id, l])).values());\n}\n\n/**\n * Check if two lenses are alternatives to each other\n */\nexport function areLensesAlternatives(lensId1: string, lensId2: string): boolean {\n const lens1 = getLensById(lensId1);\n const lens2 = getLensById(lensId2);\n\n if (!lens1 || !lens2) return false;\n if (lens1.category !== lens2.category) return false;\n\n return (\n lens1.alternativeTo?.includes(lensId2) ||\n lens2.alternativeTo?.includes(lensId1) ||\n false\n );\n}\n\n/**\n * Get all lenses that output file metrics (for File City visualization)\n */\nexport function getLensesWithFileMetrics(): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.outputsFileMetrics);\n}\n\n/**\n * Get all lenses that output aggregate scores (for Quality Hexagon)\n */\nexport function getLensesWithAggregates(): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.outputsAggregate);\n}\n\n// ============================================================\n// Color Mode Helpers (for File City)\n// ============================================================\n\n/**\n * Get the appropriate color mode (lens ID) for a category based on which lenses ran\n * Returns the first lens that ran for the category, preferring alternatives in order\n */\nexport function getColorModeForCategory(\n category: LensCategory,\n lensesRan: string[]\n): string | null {\n const lensesInCategory = getLensesByCategory(category);\n\n // Find the first lens that ran\n for (const lensId of lensesRan) {\n if (lensesInCategory.some((lens) => lens.id === lensId)) {\n return lensId;\n }\n }\n\n return null;\n}\n\n/**\n * Get display name for a lens (for UI labels)\n */\nexport function getLensDisplayName(lensId: string): string {\n return getLensById(lensId)?.name ?? lensId;\n}\n\n/**\n * Get color scheme for a lens (for File City layer rendering)\n */\nexport function getLensColorScheme(lensId: string): 'issues' | 'coverage' | 'binary' {\n return getLensById(lensId)?.colorScheme ?? 'issues';\n}\n\n// ============================================================\n// Category Helpers\n// ============================================================\n\n/**\n * Get category configuration\n */\nexport function getCategoryConfig(category: LensCategory): CategoryConfig | undefined {\n return CATEGORY_CONFIGS.find((c) => c.id === category);\n}\n\n/**\n * Get category display name\n */\nexport function getCategoryDisplayName(category: LensCategory): string {\n return getCategoryConfig(category)?.name ?? category;\n}\n\n/**\n * Check if a category uses inverted scale (lower is better)\n */\nexport function isCategoryInverted(category: LensCategory): boolean {\n return getCategoryConfig(category)?.invertedScale ?? false;\n}\n\n// ============================================================\n// Language Helpers\n// ============================================================\n\n/**\n * Get language configuration\n */\nexport function getLanguageConfig(language: Language): LanguageConfig | undefined {\n return LANGUAGE_CONFIGS.find((l) => l.id === language);\n}\n\n/**\n * Detect language from file extension\n */\nexport function detectLanguageFromExtension(extension: string): Language | undefined {\n const normalizedExt = extension.startsWith('.') ? extension : `.${extension}`;\n const config = LANGUAGE_CONFIGS.find((l) =>\n l.extensions.includes(normalizedExt.toLowerCase())\n );\n return config?.id;\n}\n\n/**\n * Get all languages that have lenses in a category\n */\nexport function getLanguagesForCategory(category: LensCategory): Language[] {\n const lenses = getLensesByCategory(category);\n const languages = new Set<Language>();\n for (const lens of lenses) {\n for (const lang of lens.languages) {\n languages.add(lang);\n }\n }\n return Array.from(languages);\n}\n\n// ============================================================\n// Hexagon Metric Helpers (for Quality Hexagon UI)\n// ============================================================\n\n/**\n * Hexagon metric keys use camelCase (from QualityMetrics interface)\n * These map to LensCategory which uses kebab-case\n */\nexport type HexagonMetricKey =\n | 'linting'\n | 'formatting'\n | 'types'\n | 'tests'\n | 'deadCode'\n | 'documentation';\n\n/**\n * Map hexagon metric keys to registry LensCategory\n */\nconst HEXAGON_METRIC_TO_CATEGORY: Record<HexagonMetricKey, LensCategory> = {\n linting: 'linting',\n formatting: 'formatting',\n types: 'types',\n tests: 'tests',\n deadCode: 'dead-code',\n documentation: 'documentation',\n};\n\n/**\n * Map LensCategory back to hexagon metric keys\n */\nconst CATEGORY_TO_HEXAGON_METRIC: Partial<Record<LensCategory, HexagonMetricKey>> = {\n 'linting': 'linting',\n 'formatting': 'formatting',\n 'types': 'types',\n 'tests': 'tests',\n 'dead-code': 'deadCode',\n 'documentation': 'documentation',\n};\n\n/**\n * Get the LensCategory for a hexagon metric key\n */\nexport function getCategoryForHexagonMetric(metric: HexagonMetricKey): LensCategory {\n return HEXAGON_METRIC_TO_CATEGORY[metric];\n}\n\n/**\n * Get the hexagon metric key for a LensCategory\n */\nexport function getHexagonMetricForCategory(category: LensCategory): HexagonMetricKey | undefined {\n return CATEGORY_TO_HEXAGON_METRIC[category];\n}\n\n/**\n * Check if a lens ID belongs to a hexagon metric\n */\nexport function isLensInHexagonMetric(lensId: string, metric: HexagonMetricKey): boolean {\n const lensCategory = getCategoryForLens(lensId);\n if (!lensCategory) return false;\n return HEXAGON_METRIC_TO_CATEGORY[metric] === lensCategory;\n}\n\n/**\n * Get the color mode for a hexagon metric based on which lenses ran.\n * This is the main entry point for the QualityHexagon panel.\n */\nexport function getColorModeForHexagonMetric(\n metric: HexagonMetricKey,\n lensesRan: string[]\n): string | null {\n const category = HEXAGON_METRIC_TO_CATEGORY[metric];\n return getColorModeForCategory(category, lensesRan);\n}\n\n/**\n * Check if a hexagon metric is configured (has at least one lens that ran)\n */\nexport function isHexagonMetricConfigured(\n metric: HexagonMetricKey,\n lensesRan: string[] | undefined\n): boolean {\n // undefined = old data without lensesRan tracking, assume all configured (backwards compatibility)\n if (lensesRan === undefined) {\n return true;\n }\n // Empty array = new data, explicitly no lenses ran for this package\n if (lensesRan.length === 0) {\n return false;\n }\n return lensesRan.some((lensId) => isLensInHexagonMetric(lensId, metric));\n}\n\n/**\n * Get all hexagon metric keys\n */\nexport function getHexagonMetricKeys(): HexagonMetricKey[] {\n return Object.keys(HEXAGON_METRIC_TO_CATEGORY) as HexagonMetricKey[];\n}\n\n// ============================================================\n// Validation Helpers\n// ============================================================\n\n/**\n * Validate that a lens ID exists in the registry\n */\nexport function isValidLensId(lensId: string): boolean {\n return getLensById(lensId) !== undefined;\n}\n\n/**\n * Find lenses that ran for the same category (potential conflicts)\n */\nexport function findCategoryConflicts(\n lensesRan: string[]\n): Array<{ category: LensCategory; lenses: string[] }> {\n const byCategory = new Map<LensCategory, string[]>();\n\n for (const lensId of lensesRan) {\n const category = getCategoryForLens(lensId);\n if (category) {\n const existing = byCategory.get(category) || [];\n existing.push(lensId);\n byCategory.set(category, existing);\n }\n }\n\n const conflicts: Array<{ category: LensCategory; lenses: string[] }> = [];\n for (const [category, lenses] of byCategory) {\n if (lenses.length > 1) {\n conflicts.push({ category, lenses });\n }\n }\n\n return conflicts;\n}\n\n/**\n * Check if all required lenses produced expected outputs\n */\nexport function validateLensOutputs(\n lensesRan: string[],\n fileMetricsProduced: string[],\n aggregatesProduced: string[]\n): Array<{ lensId: string; missing: ('fileMetrics' | 'aggregate')[] }> {\n const issues: Array<{ lensId: string; missing: ('fileMetrics' | 'aggregate')[] }> = [];\n\n for (const lensId of lensesRan) {\n const lens = getLensById(lensId);\n if (!lens) continue;\n\n const missing: ('fileMetrics' | 'aggregate')[] = [];\n\n if (lens.outputsFileMetrics && !fileMetricsProduced.includes(lensId)) {\n missing.push('fileMetrics');\n }\n if (lens.outputsAggregate && !aggregatesProduced.includes(lensId)) {\n missing.push('aggregate');\n }\n\n if (missing.length > 0) {\n issues.push({ lensId, missing });\n }\n }\n\n return issues;\n}\n\n// ============================================================\n// Color Mode Helpers (for File City visualization)\n// ============================================================\n\n/**\n * Built-in color modes that don't come from quality lenses\n */\nconst BUILT_IN_COLOR_MODES: ColorModeConfig[] = [\n {\n id: 'fileTypes',\n name: 'File Types',\n description: 'Color by file extension/type',\n icon: 'FileCode',\n colorScheme: 'categorical',\n isBuiltIn: true,\n },\n {\n id: 'git',\n name: 'Git Status',\n description: 'Color by git status (modified, added, etc.)',\n icon: 'GitBranch',\n colorScheme: 'categorical',\n isBuiltIn: true,\n },\n];\n\n/**\n * Get all available color modes (built-in + lens-based)\n */\nexport function getAvailableColorModes(): ColorMode[] {\n const builtIn: ColorMode[] = ['fileTypes', 'git'];\n const lensColorModes = getLensColorModes();\n return [...builtIn, ...lensColorModes];\n}\n\n/**\n * Get all lens-based color modes (lenses that output file metrics)\n */\nexport function getLensColorModes(): LensColorMode[] {\n return LENS_REGISTRY\n .filter((lens) => lens.outputsFileMetrics)\n .map((lens) => lens.id as LensColorMode);\n}\n\n/**\n * Check if a string is a valid color mode\n */\nexport function isValidColorMode(mode: string): mode is ColorMode {\n return getAvailableColorModes().includes(mode as ColorMode);\n}\n\n/**\n * Check if a color mode is lens-based (not built-in)\n */\nexport function isLensColorMode(mode: string): mode is LensColorMode {\n return getLensColorModes().includes(mode as LensColorMode);\n}\n\n/**\n * Get configuration for a color mode\n */\nexport function getColorModeConfig(mode: ColorMode): ColorModeConfig | undefined {\n // Check built-in modes first\n const builtIn = BUILT_IN_COLOR_MODES.find((m) => m.id === mode);\n if (builtIn) return builtIn;\n\n // Check lens-based modes\n const lens = getLensById(mode);\n if (lens && lens.outputsFileMetrics) {\n const category = getCategoryConfig(lens.category);\n return {\n id: mode,\n name: lens.name,\n description: lens.description ?? `${lens.name} analysis`,\n icon: category?.icon,\n colorScheme: lens.colorScheme,\n isBuiltIn: false,\n category: lens.category,\n };\n }\n\n return undefined;\n}\n\n/**\n * Get all color mode configurations (for building UI dropdowns/lists)\n */\nexport function getAllColorModeConfigs(): ColorModeConfig[] {\n const configs: ColorModeConfig[] = [...BUILT_IN_COLOR_MODES];\n\n for (const lens of LENS_REGISTRY) {\n if (lens.outputsFileMetrics) {\n const category = getCategoryConfig(lens.category);\n configs.push({\n id: lens.id as ColorMode,\n name: lens.name,\n description: lens.description ?? `${lens.name} analysis`,\n icon: category?.icon,\n colorScheme: lens.colorScheme,\n isBuiltIn: false,\n category: lens.category,\n });\n }\n }\n\n return configs;\n}\n\n/**\n * Get color modes available for a specific language\n * (built-in modes + lens modes that support the language)\n */\nexport function getColorModesForLanguage(language: Language): ColorMode[] {\n const builtIn: ColorMode[] = ['fileTypes', 'git'];\n\n const lensColorModes = LENS_REGISTRY\n .filter((lens) => lens.outputsFileMetrics && lens.languages.includes(language))\n .map((lens) => lens.id as LensColorMode);\n\n return [...builtIn, ...lensColorModes];\n}\n\n/**\n * Get color modes available based on which lenses ran\n * (built-in modes + lens modes from lensesRan list)\n */\nexport function getAvailableColorModesFromLenses(lensesRan: string[]): ColorMode[] {\n const builtIn: ColorMode[] = ['fileTypes', 'git'];\n\n const lensColorModes = lensesRan.filter((lensId) => {\n const lens = getLensById(lensId);\n return lens?.outputsFileMetrics;\n }) as LensColorMode[];\n\n return [...builtIn, ...lensColorModes];\n}\n\n/**\n * Check if a color mode is available based on which lenses ran\n */\nexport function isColorModeAvailable(mode: ColorMode, lensesRan: string[]): boolean {\n // Built-in modes are always available\n if (mode === 'fileTypes' || mode === 'git') {\n return true;\n }\n\n // Lens-based modes are available if the lens ran\n return lensesRan.includes(mode);\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -66,6 +66,35 @@ interface LanguageConfig {
66
66
  /** Icon or emoji for the language */
67
67
  icon?: string;
68
68
  }
69
+ /**
70
+ * Built-in color modes that don't come from quality lenses
71
+ */
72
+ type BuiltInColorMode = 'fileTypes' | 'git';
73
+ /**
74
+ * Lens-based color modes derived from LENS_REGISTRY
75
+ * These are lens IDs that output file metrics
76
+ */
77
+ type LensColorMode = 'eslint' | 'biome-lint' | 'oxlint' | 'ruff' | 'pylint' | 'golangci-lint' | 'clippy' | 'prettier' | 'biome-format' | 'black' | 'ruff-format' | 'gofmt' | 'rustfmt' | 'typescript' | 'mypy' | 'pyright' | 'go-vet' | 'jest' | 'vitest' | 'bun-test' | 'pytest' | 'go-test' | 'cargo-test' | 'knip' | 'vulture' | 'alexandria' | 'bandit';
78
+ /**
79
+ * All available color modes for File City visualization
80
+ */
81
+ type ColorMode = BuiltInColorMode | LensColorMode;
82
+ /**
83
+ * Configuration for a color mode (for UI display)
84
+ */
85
+ interface ColorModeConfig {
86
+ id: ColorMode;
87
+ name: string;
88
+ description: string;
89
+ /** Icon name (for lucide-react or similar) */
90
+ icon?: string;
91
+ /** The color scheme to use for visualization */
92
+ colorScheme: ColorScheme | 'categorical';
93
+ /** Whether this is a built-in mode (not from a lens) */
94
+ isBuiltIn: boolean;
95
+ /** The lens category this mode belongs to (if lens-based) */
96
+ category?: LensCategory;
97
+ }
69
98
 
70
99
  /**
71
100
  * Central registry of all quality lenses
@@ -206,5 +235,43 @@ declare function validateLensOutputs(lensesRan: string[], fileMetricsProduced: s
206
235
  lensId: string;
207
236
  missing: ('fileMetrics' | 'aggregate')[];
208
237
  }>;
238
+ /**
239
+ * Get all available color modes (built-in + lens-based)
240
+ */
241
+ declare function getAvailableColorModes(): ColorMode[];
242
+ /**
243
+ * Get all lens-based color modes (lenses that output file metrics)
244
+ */
245
+ declare function getLensColorModes(): LensColorMode[];
246
+ /**
247
+ * Check if a string is a valid color mode
248
+ */
249
+ declare function isValidColorMode(mode: string): mode is ColorMode;
250
+ /**
251
+ * Check if a color mode is lens-based (not built-in)
252
+ */
253
+ declare function isLensColorMode(mode: string): mode is LensColorMode;
254
+ /**
255
+ * Get configuration for a color mode
256
+ */
257
+ declare function getColorModeConfig(mode: ColorMode): ColorModeConfig | undefined;
258
+ /**
259
+ * Get all color mode configurations (for building UI dropdowns/lists)
260
+ */
261
+ declare function getAllColorModeConfigs(): ColorModeConfig[];
262
+ /**
263
+ * Get color modes available for a specific language
264
+ * (built-in modes + lens modes that support the language)
265
+ */
266
+ declare function getColorModesForLanguage(language: Language): ColorMode[];
267
+ /**
268
+ * Get color modes available based on which lenses ran
269
+ * (built-in modes + lens modes from lensesRan list)
270
+ */
271
+ declare function getAvailableColorModesFromLenses(lensesRan: string[]): ColorMode[];
272
+ /**
273
+ * Check if a color mode is available based on which lenses ran
274
+ */
275
+ declare function isColorModeAvailable(mode: ColorMode, lensesRan: string[]): boolean;
209
276
 
210
- export { CATEGORY_CONFIGS, type CategoryConfig, type ColorScheme, type HexagonMetricKey, LANGUAGE_CONFIGS, LENS_REGISTRY, type Language, type LanguageConfig, type LensCategory, type LensMetadata, areLensesAlternatives, detectLanguageFromExtension, findCategoryConflicts, getAlternatives, getCategoryConfig, getCategoryDisplayName, getCategoryForHexagonMetric, getCategoryForLens, getColorModeForCategory, getColorModeForHexagonMetric, getHexagonMetricForCategory, getHexagonMetricKeys, getLanguageConfig, getLanguagesForCategory, getLensById, getLensColorScheme, getLensDisplayName, getLensesByCategory, getLensesByCategoryAndLanguage, getLensesByLanguage, getLensesWithAggregates, getLensesWithFileMetrics, isCategoryInverted, isHexagonMetricConfigured, isLensInHexagonMetric, isValidLensId, validateLensOutputs };
277
+ export { type BuiltInColorMode, CATEGORY_CONFIGS, type CategoryConfig, type ColorMode, type ColorModeConfig, type ColorScheme, type HexagonMetricKey, LANGUAGE_CONFIGS, LENS_REGISTRY, type Language, type LanguageConfig, type LensCategory, type LensColorMode, type LensMetadata, areLensesAlternatives, detectLanguageFromExtension, findCategoryConflicts, getAllColorModeConfigs, getAlternatives, getAvailableColorModes, getAvailableColorModesFromLenses, getCategoryConfig, getCategoryDisplayName, getCategoryForHexagonMetric, getCategoryForLens, getColorModeConfig, getColorModeForCategory, getColorModeForHexagonMetric, getColorModesForLanguage, getHexagonMetricForCategory, getHexagonMetricKeys, getLanguageConfig, getLanguagesForCategory, getLensById, getLensColorModes, getLensColorScheme, getLensDisplayName, getLensesByCategory, getLensesByCategoryAndLanguage, getLensesByLanguage, getLensesWithAggregates, getLensesWithFileMetrics, isCategoryInverted, isColorModeAvailable, isHexagonMetricConfigured, isLensColorMode, isLensInHexagonMetric, isValidColorMode, isValidLensId, validateLensOutputs };
package/dist/index.d.ts CHANGED
@@ -66,6 +66,35 @@ interface LanguageConfig {
66
66
  /** Icon or emoji for the language */
67
67
  icon?: string;
68
68
  }
69
+ /**
70
+ * Built-in color modes that don't come from quality lenses
71
+ */
72
+ type BuiltInColorMode = 'fileTypes' | 'git';
73
+ /**
74
+ * Lens-based color modes derived from LENS_REGISTRY
75
+ * These are lens IDs that output file metrics
76
+ */
77
+ type LensColorMode = 'eslint' | 'biome-lint' | 'oxlint' | 'ruff' | 'pylint' | 'golangci-lint' | 'clippy' | 'prettier' | 'biome-format' | 'black' | 'ruff-format' | 'gofmt' | 'rustfmt' | 'typescript' | 'mypy' | 'pyright' | 'go-vet' | 'jest' | 'vitest' | 'bun-test' | 'pytest' | 'go-test' | 'cargo-test' | 'knip' | 'vulture' | 'alexandria' | 'bandit';
78
+ /**
79
+ * All available color modes for File City visualization
80
+ */
81
+ type ColorMode = BuiltInColorMode | LensColorMode;
82
+ /**
83
+ * Configuration for a color mode (for UI display)
84
+ */
85
+ interface ColorModeConfig {
86
+ id: ColorMode;
87
+ name: string;
88
+ description: string;
89
+ /** Icon name (for lucide-react or similar) */
90
+ icon?: string;
91
+ /** The color scheme to use for visualization */
92
+ colorScheme: ColorScheme | 'categorical';
93
+ /** Whether this is a built-in mode (not from a lens) */
94
+ isBuiltIn: boolean;
95
+ /** The lens category this mode belongs to (if lens-based) */
96
+ category?: LensCategory;
97
+ }
69
98
 
70
99
  /**
71
100
  * Central registry of all quality lenses
@@ -206,5 +235,43 @@ declare function validateLensOutputs(lensesRan: string[], fileMetricsProduced: s
206
235
  lensId: string;
207
236
  missing: ('fileMetrics' | 'aggregate')[];
208
237
  }>;
238
+ /**
239
+ * Get all available color modes (built-in + lens-based)
240
+ */
241
+ declare function getAvailableColorModes(): ColorMode[];
242
+ /**
243
+ * Get all lens-based color modes (lenses that output file metrics)
244
+ */
245
+ declare function getLensColorModes(): LensColorMode[];
246
+ /**
247
+ * Check if a string is a valid color mode
248
+ */
249
+ declare function isValidColorMode(mode: string): mode is ColorMode;
250
+ /**
251
+ * Check if a color mode is lens-based (not built-in)
252
+ */
253
+ declare function isLensColorMode(mode: string): mode is LensColorMode;
254
+ /**
255
+ * Get configuration for a color mode
256
+ */
257
+ declare function getColorModeConfig(mode: ColorMode): ColorModeConfig | undefined;
258
+ /**
259
+ * Get all color mode configurations (for building UI dropdowns/lists)
260
+ */
261
+ declare function getAllColorModeConfigs(): ColorModeConfig[];
262
+ /**
263
+ * Get color modes available for a specific language
264
+ * (built-in modes + lens modes that support the language)
265
+ */
266
+ declare function getColorModesForLanguage(language: Language): ColorMode[];
267
+ /**
268
+ * Get color modes available based on which lenses ran
269
+ * (built-in modes + lens modes from lensesRan list)
270
+ */
271
+ declare function getAvailableColorModesFromLenses(lensesRan: string[]): ColorMode[];
272
+ /**
273
+ * Check if a color mode is available based on which lenses ran
274
+ */
275
+ declare function isColorModeAvailable(mode: ColorMode, lensesRan: string[]): boolean;
209
276
 
210
- export { CATEGORY_CONFIGS, type CategoryConfig, type ColorScheme, type HexagonMetricKey, LANGUAGE_CONFIGS, LENS_REGISTRY, type Language, type LanguageConfig, type LensCategory, type LensMetadata, areLensesAlternatives, detectLanguageFromExtension, findCategoryConflicts, getAlternatives, getCategoryConfig, getCategoryDisplayName, getCategoryForHexagonMetric, getCategoryForLens, getColorModeForCategory, getColorModeForHexagonMetric, getHexagonMetricForCategory, getHexagonMetricKeys, getLanguageConfig, getLanguagesForCategory, getLensById, getLensColorScheme, getLensDisplayName, getLensesByCategory, getLensesByCategoryAndLanguage, getLensesByLanguage, getLensesWithAggregates, getLensesWithFileMetrics, isCategoryInverted, isHexagonMetricConfigured, isLensInHexagonMetric, isValidLensId, validateLensOutputs };
277
+ export { type BuiltInColorMode, CATEGORY_CONFIGS, type CategoryConfig, type ColorMode, type ColorModeConfig, type ColorScheme, type HexagonMetricKey, LANGUAGE_CONFIGS, LENS_REGISTRY, type Language, type LanguageConfig, type LensCategory, type LensColorMode, type LensMetadata, areLensesAlternatives, detectLanguageFromExtension, findCategoryConflicts, getAllColorModeConfigs, getAlternatives, getAvailableColorModes, getAvailableColorModesFromLenses, getCategoryConfig, getCategoryDisplayName, getCategoryForHexagonMetric, getCategoryForLens, getColorModeConfig, getColorModeForCategory, getColorModeForHexagonMetric, getColorModesForLanguage, getHexagonMetricForCategory, getHexagonMetricKeys, getLanguageConfig, getLanguagesForCategory, getLensById, getLensColorModes, getLensColorScheme, getLensDisplayName, getLensesByCategory, getLensesByCategoryAndLanguage, getLensesByLanguage, getLensesWithAggregates, getLensesWithFileMetrics, isCategoryInverted, isColorModeAvailable, isHexagonMetricConfigured, isLensColorMode, isLensInHexagonMetric, isValidColorMode, isValidLensId, validateLensOutputs };
package/dist/index.js CHANGED
@@ -641,6 +641,93 @@ function validateLensOutputs(lensesRan, fileMetricsProduced, aggregatesProduced)
641
641
  }
642
642
  return issues;
643
643
  }
644
+ var BUILT_IN_COLOR_MODES = [
645
+ {
646
+ id: "fileTypes",
647
+ name: "File Types",
648
+ description: "Color by file extension/type",
649
+ icon: "FileCode",
650
+ colorScheme: "categorical",
651
+ isBuiltIn: true
652
+ },
653
+ {
654
+ id: "git",
655
+ name: "Git Status",
656
+ description: "Color by git status (modified, added, etc.)",
657
+ icon: "GitBranch",
658
+ colorScheme: "categorical",
659
+ isBuiltIn: true
660
+ }
661
+ ];
662
+ function getAvailableColorModes() {
663
+ const builtIn = ["fileTypes", "git"];
664
+ const lensColorModes = getLensColorModes();
665
+ return [...builtIn, ...lensColorModes];
666
+ }
667
+ function getLensColorModes() {
668
+ return LENS_REGISTRY.filter((lens) => lens.outputsFileMetrics).map((lens) => lens.id);
669
+ }
670
+ function isValidColorMode(mode) {
671
+ return getAvailableColorModes().includes(mode);
672
+ }
673
+ function isLensColorMode(mode) {
674
+ return getLensColorModes().includes(mode);
675
+ }
676
+ function getColorModeConfig(mode) {
677
+ const builtIn = BUILT_IN_COLOR_MODES.find((m) => m.id === mode);
678
+ if (builtIn) return builtIn;
679
+ const lens = getLensById(mode);
680
+ if (lens && lens.outputsFileMetrics) {
681
+ const category = getCategoryConfig(lens.category);
682
+ return {
683
+ id: mode,
684
+ name: lens.name,
685
+ description: lens.description ?? `${lens.name} analysis`,
686
+ icon: category?.icon,
687
+ colorScheme: lens.colorScheme,
688
+ isBuiltIn: false,
689
+ category: lens.category
690
+ };
691
+ }
692
+ return void 0;
693
+ }
694
+ function getAllColorModeConfigs() {
695
+ const configs = [...BUILT_IN_COLOR_MODES];
696
+ for (const lens of LENS_REGISTRY) {
697
+ if (lens.outputsFileMetrics) {
698
+ const category = getCategoryConfig(lens.category);
699
+ configs.push({
700
+ id: lens.id,
701
+ name: lens.name,
702
+ description: lens.description ?? `${lens.name} analysis`,
703
+ icon: category?.icon,
704
+ colorScheme: lens.colorScheme,
705
+ isBuiltIn: false,
706
+ category: lens.category
707
+ });
708
+ }
709
+ }
710
+ return configs;
711
+ }
712
+ function getColorModesForLanguage(language) {
713
+ const builtIn = ["fileTypes", "git"];
714
+ const lensColorModes = LENS_REGISTRY.filter((lens) => lens.outputsFileMetrics && lens.languages.includes(language)).map((lens) => lens.id);
715
+ return [...builtIn, ...lensColorModes];
716
+ }
717
+ function getAvailableColorModesFromLenses(lensesRan) {
718
+ const builtIn = ["fileTypes", "git"];
719
+ const lensColorModes = lensesRan.filter((lensId) => {
720
+ const lens = getLensById(lensId);
721
+ return lens?.outputsFileMetrics;
722
+ });
723
+ return [...builtIn, ...lensColorModes];
724
+ }
725
+ function isColorModeAvailable(mode, lensesRan) {
726
+ if (mode === "fileTypes" || mode === "git") {
727
+ return true;
728
+ }
729
+ return lensesRan.includes(mode);
730
+ }
644
731
  export {
645
732
  CATEGORY_CONFIGS,
646
733
  LANGUAGE_CONFIGS,
@@ -648,18 +735,24 @@ export {
648
735
  areLensesAlternatives,
649
736
  detectLanguageFromExtension,
650
737
  findCategoryConflicts,
738
+ getAllColorModeConfigs,
651
739
  getAlternatives,
740
+ getAvailableColorModes,
741
+ getAvailableColorModesFromLenses,
652
742
  getCategoryConfig,
653
743
  getCategoryDisplayName,
654
744
  getCategoryForHexagonMetric,
655
745
  getCategoryForLens,
746
+ getColorModeConfig,
656
747
  getColorModeForCategory,
657
748
  getColorModeForHexagonMetric,
749
+ getColorModesForLanguage,
658
750
  getHexagonMetricForCategory,
659
751
  getHexagonMetricKeys,
660
752
  getLanguageConfig,
661
753
  getLanguagesForCategory,
662
754
  getLensById,
755
+ getLensColorModes,
663
756
  getLensColorScheme,
664
757
  getLensDisplayName,
665
758
  getLensesByCategory,
@@ -668,8 +761,11 @@ export {
668
761
  getLensesWithAggregates,
669
762
  getLensesWithFileMetrics,
670
763
  isCategoryInverted,
764
+ isColorModeAvailable,
671
765
  isHexagonMetricConfigured,
766
+ isLensColorMode,
672
767
  isLensInHexagonMetric,
768
+ isValidColorMode,
673
769
  isValidLensId,
674
770
  validateLensOutputs
675
771
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/registry.ts","../src/helpers.ts"],"sourcesContent":["import type { LensMetadata, CategoryConfig, LanguageConfig } from './types.js';\n\n/**\n * Central registry of all quality lenses\n *\n * When adding a new lens:\n * 1. Add it to this registry with complete metadata\n * 2. Implement the lens in @principal-ai/codebase-quality-lenses\n * 3. The UI packages will automatically discover and support it\n */\nexport const LENS_REGISTRY: LensMetadata[] = [\n // ============================================================\n // LINTING - Code style and bug detection\n // ============================================================\n\n // TypeScript/JavaScript linting\n {\n id: 'eslint',\n name: 'ESLint',\n category: 'linting',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Pluggable linting utility for JavaScript and TypeScript',\n command: 'eslint',\n },\n {\n id: 'biome-lint',\n name: 'Biome Lint',\n category: 'linting',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['eslint'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Fast linter for JavaScript and TypeScript',\n command: 'biome lint',\n },\n {\n id: 'oxlint',\n name: 'OxLint',\n category: 'linting',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['eslint', 'biome-lint'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Blazing fast JavaScript/TypeScript linter',\n command: 'oxlint',\n },\n\n // Python linting\n {\n id: 'ruff',\n name: 'Ruff',\n category: 'linting',\n languages: ['python'],\n alternativeTo: ['pylint', 'flake8'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Extremely fast Python linter',\n command: 'ruff check',\n },\n {\n id: 'pylint',\n name: 'Pylint',\n category: 'linting',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Python static code analyzer',\n command: 'pylint',\n },\n\n // Go linting\n {\n id: 'golangci-lint',\n name: 'golangci-lint',\n category: 'linting',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Fast linters runner for Go',\n command: 'golangci-lint run',\n },\n\n // Rust linting\n {\n id: 'clippy',\n name: 'Clippy',\n category: 'linting',\n languages: ['rust'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Rust linter',\n command: 'cargo clippy',\n },\n\n // ============================================================\n // FORMATTING - Code formatting\n // ============================================================\n\n // TypeScript/JavaScript formatting\n {\n id: 'prettier',\n name: 'Prettier',\n category: 'formatting',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Opinionated code formatter',\n command: 'prettier --check',\n },\n {\n id: 'biome-format',\n name: 'Biome Format',\n category: 'formatting',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['prettier'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Fast code formatter for JavaScript and TypeScript',\n command: 'biome format',\n },\n\n // Python formatting\n {\n id: 'black',\n name: 'Black',\n category: 'formatting',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'The uncompromising Python code formatter',\n command: 'black --check',\n },\n {\n id: 'ruff-format',\n name: 'Ruff Format',\n category: 'formatting',\n languages: ['python'],\n alternativeTo: ['black'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Fast Python formatter (Ruff)',\n command: 'ruff format --check',\n },\n\n // Go formatting\n {\n id: 'gofmt',\n name: 'gofmt',\n category: 'formatting',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Go code formatter',\n command: 'gofmt -l',\n },\n\n // Rust formatting\n {\n id: 'rustfmt',\n name: 'rustfmt',\n category: 'formatting',\n languages: ['rust'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Rust code formatter',\n command: 'cargo fmt --check',\n },\n\n // ============================================================\n // TYPES - Type checking\n // ============================================================\n\n // TypeScript\n {\n id: 'typescript',\n name: 'TypeScript',\n category: 'types',\n languages: ['typescript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'TypeScript type checker',\n command: 'tsc --noEmit',\n },\n\n // Python type checking\n {\n id: 'mypy',\n name: 'MyPy',\n category: 'types',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Static type checker for Python',\n command: 'mypy',\n },\n {\n id: 'pyright',\n name: 'Pyright',\n category: 'types',\n languages: ['python'],\n alternativeTo: ['mypy'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Static type checker for Python',\n command: 'pyright',\n },\n\n // Go type checking (built into compiler)\n {\n id: 'go-vet',\n name: 'Go Vet',\n category: 'types',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Go static analyzer',\n command: 'go vet',\n },\n\n // ============================================================\n // TESTS - Test coverage and results\n // ============================================================\n\n // JavaScript/TypeScript testing\n {\n id: 'jest',\n name: 'Jest',\n category: 'tests',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'JavaScript testing framework',\n command: 'jest --coverage',\n },\n {\n id: 'vitest',\n name: 'Vitest',\n category: 'tests',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['jest'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Vite-native testing framework',\n command: 'vitest run --coverage',\n },\n {\n id: 'bun-test',\n name: 'Bun Test',\n category: 'tests',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['jest', 'vitest'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Bun native test runner',\n command: 'bun test',\n },\n\n // Python testing\n {\n id: 'pytest',\n name: 'Pytest',\n category: 'tests',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Python testing framework',\n command: 'pytest --cov',\n },\n\n // Go testing\n {\n id: 'go-test',\n name: 'Go Test',\n category: 'tests',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Go test runner',\n command: 'go test -cover',\n },\n\n // Rust testing\n {\n id: 'cargo-test',\n name: 'Cargo Test',\n category: 'tests',\n languages: ['rust'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Rust test runner',\n command: 'cargo test',\n },\n\n // ============================================================\n // DEAD CODE - Unused code detection\n // ============================================================\n\n // TypeScript/JavaScript\n {\n id: 'knip',\n name: 'Knip',\n category: 'dead-code',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Find unused files, dependencies and exports',\n command: 'knip',\n },\n\n // Python\n {\n id: 'vulture',\n name: 'Vulture',\n category: 'dead-code',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Find dead Python code',\n command: 'vulture',\n },\n\n // ============================================================\n // DOCUMENTATION - Documentation coverage\n // ============================================================\n\n {\n id: 'alexandria',\n name: 'Alexandria',\n category: 'documentation',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Documentation coverage checker',\n command: 'alexandria lint',\n },\n {\n id: 'typedoc',\n name: 'TypeDoc',\n category: 'documentation',\n languages: ['typescript'],\n outputsFileMetrics: false,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'TypeScript documentation generator',\n command: 'typedoc',\n },\n\n // ============================================================\n // SECURITY - Security scanning\n // ============================================================\n\n {\n id: 'npm-audit',\n name: 'npm audit',\n category: 'security',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: false,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Check for known vulnerabilities in dependencies',\n command: 'npm audit',\n },\n {\n id: 'bandit',\n name: 'Bandit',\n category: 'security',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Python security linter',\n command: 'bandit -r',\n },\n];\n\n/**\n * Category configurations for UI display\n */\nexport const CATEGORY_CONFIGS: CategoryConfig[] = [\n {\n id: 'linting',\n name: 'Linting',\n description: 'Code style and bug detection',\n icon: 'AlertCircle',\n },\n {\n id: 'formatting',\n name: 'Formatting',\n description: 'Code formatting consistency',\n icon: 'AlignLeft',\n },\n {\n id: 'types',\n name: 'Types',\n description: 'Type safety and checking',\n icon: 'FileType',\n },\n {\n id: 'tests',\n name: 'Tests',\n description: 'Test coverage and results',\n icon: 'TestTube',\n },\n {\n id: 'dead-code',\n name: 'Dead Code',\n description: 'Unused code detection',\n icon: 'Trash2',\n invertedScale: true,\n },\n {\n id: 'documentation',\n name: 'Documentation',\n description: 'Documentation coverage',\n icon: 'FileText',\n },\n {\n id: 'security',\n name: 'Security',\n description: 'Security vulnerability scanning',\n icon: 'Shield',\n },\n {\n id: 'complexity',\n name: 'Complexity',\n description: 'Code complexity metrics',\n icon: 'GitBranch',\n },\n];\n\n/**\n * Language configurations for UI display\n */\nexport const LANGUAGE_CONFIGS: LanguageConfig[] = [\n {\n id: 'typescript',\n name: 'TypeScript',\n extensions: ['.ts', '.tsx', '.mts', '.cts'],\n icon: 'TS',\n },\n {\n id: 'javascript',\n name: 'JavaScript',\n extensions: ['.js', '.jsx', '.mjs', '.cjs'],\n icon: 'JS',\n },\n {\n id: 'python',\n name: 'Python',\n extensions: ['.py', '.pyi'],\n icon: 'PY',\n },\n {\n id: 'go',\n name: 'Go',\n extensions: ['.go'],\n icon: 'GO',\n },\n {\n id: 'rust',\n name: 'Rust',\n extensions: ['.rs'],\n icon: 'RS',\n },\n {\n id: 'java',\n name: 'Java',\n extensions: ['.java'],\n icon: 'JV',\n },\n {\n id: 'csharp',\n name: 'C#',\n extensions: ['.cs'],\n icon: 'C#',\n },\n {\n id: 'ruby',\n name: 'Ruby',\n extensions: ['.rb'],\n icon: 'RB',\n },\n {\n id: 'php',\n name: 'PHP',\n extensions: ['.php'],\n icon: 'PHP',\n },\n];\n","import type { LensMetadata, LensCategory, Language, CategoryConfig, LanguageConfig } from './types.js';\nimport { LENS_REGISTRY, CATEGORY_CONFIGS, LANGUAGE_CONFIGS } from './registry.js';\n\n// ============================================================\n// Lens Lookups\n// ============================================================\n\n/**\n * Get lens metadata by ID\n */\nexport function getLensById(id: string): LensMetadata | undefined {\n return LENS_REGISTRY.find((lens) => lens.id === id);\n}\n\n/**\n * Get all lenses in a category\n */\nexport function getLensesByCategory(category: LensCategory): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.category === category);\n}\n\n/**\n * Get all lenses that support a language\n */\nexport function getLensesByLanguage(language: Language): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.languages.includes(language));\n}\n\n/**\n * Get lenses that support a category for a specific language\n */\nexport function getLensesByCategoryAndLanguage(\n category: LensCategory,\n language: Language\n): LensMetadata[] {\n return LENS_REGISTRY.filter(\n (lens) => lens.category === category && lens.languages.includes(language)\n );\n}\n\n/**\n * Get the category for a lens ID\n */\nexport function getCategoryForLens(lensId: string): LensCategory | undefined {\n return getLensById(lensId)?.category;\n}\n\n/**\n * Get alternative lenses for a given lens ID\n */\nexport function getAlternatives(lensId: string): LensMetadata[] {\n const lens = getLensById(lensId);\n if (!lens) return [];\n\n // Find lenses that list this one as an alternative\n const listedAsAlternative = LENS_REGISTRY.filter(\n (other) => other.alternativeTo?.includes(lensId)\n );\n\n // Find lenses that this one lists as alternatives\n const thisListsAsAlternative = lens.alternativeTo\n ? LENS_REGISTRY.filter((other) => lens.alternativeTo!.includes(other.id))\n : [];\n\n // Combine and dedupe\n const all = [...listedAsAlternative, ...thisListsAsAlternative];\n return Array.from(new Map(all.map((l) => [l.id, l])).values());\n}\n\n/**\n * Check if two lenses are alternatives to each other\n */\nexport function areLensesAlternatives(lensId1: string, lensId2: string): boolean {\n const lens1 = getLensById(lensId1);\n const lens2 = getLensById(lensId2);\n\n if (!lens1 || !lens2) return false;\n if (lens1.category !== lens2.category) return false;\n\n return (\n lens1.alternativeTo?.includes(lensId2) ||\n lens2.alternativeTo?.includes(lensId1) ||\n false\n );\n}\n\n/**\n * Get all lenses that output file metrics (for File City visualization)\n */\nexport function getLensesWithFileMetrics(): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.outputsFileMetrics);\n}\n\n/**\n * Get all lenses that output aggregate scores (for Quality Hexagon)\n */\nexport function getLensesWithAggregates(): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.outputsAggregate);\n}\n\n// ============================================================\n// Color Mode Helpers (for File City)\n// ============================================================\n\n/**\n * Get the appropriate color mode (lens ID) for a category based on which lenses ran\n * Returns the first lens that ran for the category, preferring alternatives in order\n */\nexport function getColorModeForCategory(\n category: LensCategory,\n lensesRan: string[]\n): string | null {\n const lensesInCategory = getLensesByCategory(category);\n\n // Find the first lens that ran\n for (const lensId of lensesRan) {\n if (lensesInCategory.some((lens) => lens.id === lensId)) {\n return lensId;\n }\n }\n\n return null;\n}\n\n/**\n * Get display name for a lens (for UI labels)\n */\nexport function getLensDisplayName(lensId: string): string {\n return getLensById(lensId)?.name ?? lensId;\n}\n\n/**\n * Get color scheme for a lens (for File City layer rendering)\n */\nexport function getLensColorScheme(lensId: string): 'issues' | 'coverage' | 'binary' {\n return getLensById(lensId)?.colorScheme ?? 'issues';\n}\n\n// ============================================================\n// Category Helpers\n// ============================================================\n\n/**\n * Get category configuration\n */\nexport function getCategoryConfig(category: LensCategory): CategoryConfig | undefined {\n return CATEGORY_CONFIGS.find((c) => c.id === category);\n}\n\n/**\n * Get category display name\n */\nexport function getCategoryDisplayName(category: LensCategory): string {\n return getCategoryConfig(category)?.name ?? category;\n}\n\n/**\n * Check if a category uses inverted scale (lower is better)\n */\nexport function isCategoryInverted(category: LensCategory): boolean {\n return getCategoryConfig(category)?.invertedScale ?? false;\n}\n\n// ============================================================\n// Language Helpers\n// ============================================================\n\n/**\n * Get language configuration\n */\nexport function getLanguageConfig(language: Language): LanguageConfig | undefined {\n return LANGUAGE_CONFIGS.find((l) => l.id === language);\n}\n\n/**\n * Detect language from file extension\n */\nexport function detectLanguageFromExtension(extension: string): Language | undefined {\n const normalizedExt = extension.startsWith('.') ? extension : `.${extension}`;\n const config = LANGUAGE_CONFIGS.find((l) =>\n l.extensions.includes(normalizedExt.toLowerCase())\n );\n return config?.id;\n}\n\n/**\n * Get all languages that have lenses in a category\n */\nexport function getLanguagesForCategory(category: LensCategory): Language[] {\n const lenses = getLensesByCategory(category);\n const languages = new Set<Language>();\n for (const lens of lenses) {\n for (const lang of lens.languages) {\n languages.add(lang);\n }\n }\n return Array.from(languages);\n}\n\n// ============================================================\n// Hexagon Metric Helpers (for Quality Hexagon UI)\n// ============================================================\n\n/**\n * Hexagon metric keys use camelCase (from QualityMetrics interface)\n * These map to LensCategory which uses kebab-case\n */\nexport type HexagonMetricKey =\n | 'linting'\n | 'formatting'\n | 'types'\n | 'tests'\n | 'deadCode'\n | 'documentation';\n\n/**\n * Map hexagon metric keys to registry LensCategory\n */\nconst HEXAGON_METRIC_TO_CATEGORY: Record<HexagonMetricKey, LensCategory> = {\n linting: 'linting',\n formatting: 'formatting',\n types: 'types',\n tests: 'tests',\n deadCode: 'dead-code',\n documentation: 'documentation',\n};\n\n/**\n * Map LensCategory back to hexagon metric keys\n */\nconst CATEGORY_TO_HEXAGON_METRIC: Partial<Record<LensCategory, HexagonMetricKey>> = {\n 'linting': 'linting',\n 'formatting': 'formatting',\n 'types': 'types',\n 'tests': 'tests',\n 'dead-code': 'deadCode',\n 'documentation': 'documentation',\n};\n\n/**\n * Get the LensCategory for a hexagon metric key\n */\nexport function getCategoryForHexagonMetric(metric: HexagonMetricKey): LensCategory {\n return HEXAGON_METRIC_TO_CATEGORY[metric];\n}\n\n/**\n * Get the hexagon metric key for a LensCategory\n */\nexport function getHexagonMetricForCategory(category: LensCategory): HexagonMetricKey | undefined {\n return CATEGORY_TO_HEXAGON_METRIC[category];\n}\n\n/**\n * Check if a lens ID belongs to a hexagon metric\n */\nexport function isLensInHexagonMetric(lensId: string, metric: HexagonMetricKey): boolean {\n const lensCategory = getCategoryForLens(lensId);\n if (!lensCategory) return false;\n return HEXAGON_METRIC_TO_CATEGORY[metric] === lensCategory;\n}\n\n/**\n * Get the color mode for a hexagon metric based on which lenses ran.\n * This is the main entry point for the QualityHexagon panel.\n */\nexport function getColorModeForHexagonMetric(\n metric: HexagonMetricKey,\n lensesRan: string[]\n): string | null {\n const category = HEXAGON_METRIC_TO_CATEGORY[metric];\n return getColorModeForCategory(category, lensesRan);\n}\n\n/**\n * Check if a hexagon metric is configured (has at least one lens that ran)\n */\nexport function isHexagonMetricConfigured(\n metric: HexagonMetricKey,\n lensesRan: string[] | undefined\n): boolean {\n // undefined = old data without lensesRan tracking, assume all configured (backwards compatibility)\n if (lensesRan === undefined) {\n return true;\n }\n // Empty array = new data, explicitly no lenses ran for this package\n if (lensesRan.length === 0) {\n return false;\n }\n return lensesRan.some((lensId) => isLensInHexagonMetric(lensId, metric));\n}\n\n/**\n * Get all hexagon metric keys\n */\nexport function getHexagonMetricKeys(): HexagonMetricKey[] {\n return Object.keys(HEXAGON_METRIC_TO_CATEGORY) as HexagonMetricKey[];\n}\n\n// ============================================================\n// Validation Helpers\n// ============================================================\n\n/**\n * Validate that a lens ID exists in the registry\n */\nexport function isValidLensId(lensId: string): boolean {\n return getLensById(lensId) !== undefined;\n}\n\n/**\n * Find lenses that ran for the same category (potential conflicts)\n */\nexport function findCategoryConflicts(\n lensesRan: string[]\n): Array<{ category: LensCategory; lenses: string[] }> {\n const byCategory = new Map<LensCategory, string[]>();\n\n for (const lensId of lensesRan) {\n const category = getCategoryForLens(lensId);\n if (category) {\n const existing = byCategory.get(category) || [];\n existing.push(lensId);\n byCategory.set(category, existing);\n }\n }\n\n const conflicts: Array<{ category: LensCategory; lenses: string[] }> = [];\n for (const [category, lenses] of byCategory) {\n if (lenses.length > 1) {\n conflicts.push({ category, lenses });\n }\n }\n\n return conflicts;\n}\n\n/**\n * Check if all required lenses produced expected outputs\n */\nexport function validateLensOutputs(\n lensesRan: string[],\n fileMetricsProduced: string[],\n aggregatesProduced: string[]\n): Array<{ lensId: string; missing: ('fileMetrics' | 'aggregate')[] }> {\n const issues: Array<{ lensId: string; missing: ('fileMetrics' | 'aggregate')[] }> = [];\n\n for (const lensId of lensesRan) {\n const lens = getLensById(lensId);\n if (!lens) continue;\n\n const missing: ('fileMetrics' | 'aggregate')[] = [];\n\n if (lens.outputsFileMetrics && !fileMetricsProduced.includes(lensId)) {\n missing.push('fileMetrics');\n }\n if (lens.outputsAggregate && !aggregatesProduced.includes(lensId)) {\n missing.push('aggregate');\n }\n\n if (missing.length > 0) {\n issues.push({ lensId, missing });\n }\n }\n\n return issues;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/registry.ts","../src/helpers.ts"],"sourcesContent":["import type { LensMetadata, CategoryConfig, LanguageConfig } from './types.js';\n\n/**\n * Central registry of all quality lenses\n *\n * When adding a new lens:\n * 1. Add it to this registry with complete metadata\n * 2. Implement the lens in @principal-ai/codebase-quality-lenses\n * 3. The UI packages will automatically discover and support it\n */\nexport const LENS_REGISTRY: LensMetadata[] = [\n // ============================================================\n // LINTING - Code style and bug detection\n // ============================================================\n\n // TypeScript/JavaScript linting\n {\n id: 'eslint',\n name: 'ESLint',\n category: 'linting',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Pluggable linting utility for JavaScript and TypeScript',\n command: 'eslint',\n },\n {\n id: 'biome-lint',\n name: 'Biome Lint',\n category: 'linting',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['eslint'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Fast linter for JavaScript and TypeScript',\n command: 'biome lint',\n },\n {\n id: 'oxlint',\n name: 'OxLint',\n category: 'linting',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['eslint', 'biome-lint'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Blazing fast JavaScript/TypeScript linter',\n command: 'oxlint',\n },\n\n // Python linting\n {\n id: 'ruff',\n name: 'Ruff',\n category: 'linting',\n languages: ['python'],\n alternativeTo: ['pylint', 'flake8'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Extremely fast Python linter',\n command: 'ruff check',\n },\n {\n id: 'pylint',\n name: 'Pylint',\n category: 'linting',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Python static code analyzer',\n command: 'pylint',\n },\n\n // Go linting\n {\n id: 'golangci-lint',\n name: 'golangci-lint',\n category: 'linting',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Fast linters runner for Go',\n command: 'golangci-lint run',\n },\n\n // Rust linting\n {\n id: 'clippy',\n name: 'Clippy',\n category: 'linting',\n languages: ['rust'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Rust linter',\n command: 'cargo clippy',\n },\n\n // ============================================================\n // FORMATTING - Code formatting\n // ============================================================\n\n // TypeScript/JavaScript formatting\n {\n id: 'prettier',\n name: 'Prettier',\n category: 'formatting',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Opinionated code formatter',\n command: 'prettier --check',\n },\n {\n id: 'biome-format',\n name: 'Biome Format',\n category: 'formatting',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['prettier'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Fast code formatter for JavaScript and TypeScript',\n command: 'biome format',\n },\n\n // Python formatting\n {\n id: 'black',\n name: 'Black',\n category: 'formatting',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'The uncompromising Python code formatter',\n command: 'black --check',\n },\n {\n id: 'ruff-format',\n name: 'Ruff Format',\n category: 'formatting',\n languages: ['python'],\n alternativeTo: ['black'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Fast Python formatter (Ruff)',\n command: 'ruff format --check',\n },\n\n // Go formatting\n {\n id: 'gofmt',\n name: 'gofmt',\n category: 'formatting',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Go code formatter',\n command: 'gofmt -l',\n },\n\n // Rust formatting\n {\n id: 'rustfmt',\n name: 'rustfmt',\n category: 'formatting',\n languages: ['rust'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Rust code formatter',\n command: 'cargo fmt --check',\n },\n\n // ============================================================\n // TYPES - Type checking\n // ============================================================\n\n // TypeScript\n {\n id: 'typescript',\n name: 'TypeScript',\n category: 'types',\n languages: ['typescript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'TypeScript type checker',\n command: 'tsc --noEmit',\n },\n\n // Python type checking\n {\n id: 'mypy',\n name: 'MyPy',\n category: 'types',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Static type checker for Python',\n command: 'mypy',\n },\n {\n id: 'pyright',\n name: 'Pyright',\n category: 'types',\n languages: ['python'],\n alternativeTo: ['mypy'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Static type checker for Python',\n command: 'pyright',\n },\n\n // Go type checking (built into compiler)\n {\n id: 'go-vet',\n name: 'Go Vet',\n category: 'types',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Go static analyzer',\n command: 'go vet',\n },\n\n // ============================================================\n // TESTS - Test coverage and results\n // ============================================================\n\n // JavaScript/TypeScript testing\n {\n id: 'jest',\n name: 'Jest',\n category: 'tests',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'JavaScript testing framework',\n command: 'jest --coverage',\n },\n {\n id: 'vitest',\n name: 'Vitest',\n category: 'tests',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['jest'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Vite-native testing framework',\n command: 'vitest run --coverage',\n },\n {\n id: 'bun-test',\n name: 'Bun Test',\n category: 'tests',\n languages: ['typescript', 'javascript'],\n alternativeTo: ['jest', 'vitest'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Bun native test runner',\n command: 'bun test',\n },\n\n // Python testing\n {\n id: 'pytest',\n name: 'Pytest',\n category: 'tests',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Python testing framework',\n command: 'pytest --cov',\n },\n\n // Go testing\n {\n id: 'go-test',\n name: 'Go Test',\n category: 'tests',\n languages: ['go'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Go test runner',\n command: 'go test -cover',\n },\n\n // Rust testing\n {\n id: 'cargo-test',\n name: 'Cargo Test',\n category: 'tests',\n languages: ['rust'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'Rust test runner',\n command: 'cargo test',\n },\n\n // ============================================================\n // DEAD CODE - Unused code detection\n // ============================================================\n\n // TypeScript/JavaScript\n {\n id: 'knip',\n name: 'Knip',\n category: 'dead-code',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Find unused files, dependencies and exports',\n command: 'knip',\n },\n\n // Python\n {\n id: 'vulture',\n name: 'Vulture',\n category: 'dead-code',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Find dead Python code',\n command: 'vulture',\n },\n\n // ============================================================\n // DOCUMENTATION - Documentation coverage\n // ============================================================\n\n {\n id: 'alexandria',\n name: 'Alexandria',\n category: 'documentation',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'binary',\n description: 'Documentation coverage checker',\n command: 'alexandria lint',\n },\n {\n id: 'typedoc',\n name: 'TypeDoc',\n category: 'documentation',\n languages: ['typescript'],\n outputsFileMetrics: false,\n outputsAggregate: true,\n colorScheme: 'coverage',\n description: 'TypeScript documentation generator',\n command: 'typedoc',\n },\n\n // ============================================================\n // SECURITY - Security scanning\n // ============================================================\n\n {\n id: 'npm-audit',\n name: 'npm audit',\n category: 'security',\n languages: ['typescript', 'javascript'],\n outputsFileMetrics: false,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Check for known vulnerabilities in dependencies',\n command: 'npm audit',\n },\n {\n id: 'bandit',\n name: 'Bandit',\n category: 'security',\n languages: ['python'],\n outputsFileMetrics: true,\n outputsAggregate: true,\n colorScheme: 'issues',\n description: 'Python security linter',\n command: 'bandit -r',\n },\n];\n\n/**\n * Category configurations for UI display\n */\nexport const CATEGORY_CONFIGS: CategoryConfig[] = [\n {\n id: 'linting',\n name: 'Linting',\n description: 'Code style and bug detection',\n icon: 'AlertCircle',\n },\n {\n id: 'formatting',\n name: 'Formatting',\n description: 'Code formatting consistency',\n icon: 'AlignLeft',\n },\n {\n id: 'types',\n name: 'Types',\n description: 'Type safety and checking',\n icon: 'FileType',\n },\n {\n id: 'tests',\n name: 'Tests',\n description: 'Test coverage and results',\n icon: 'TestTube',\n },\n {\n id: 'dead-code',\n name: 'Dead Code',\n description: 'Unused code detection',\n icon: 'Trash2',\n invertedScale: true,\n },\n {\n id: 'documentation',\n name: 'Documentation',\n description: 'Documentation coverage',\n icon: 'FileText',\n },\n {\n id: 'security',\n name: 'Security',\n description: 'Security vulnerability scanning',\n icon: 'Shield',\n },\n {\n id: 'complexity',\n name: 'Complexity',\n description: 'Code complexity metrics',\n icon: 'GitBranch',\n },\n];\n\n/**\n * Language configurations for UI display\n */\nexport const LANGUAGE_CONFIGS: LanguageConfig[] = [\n {\n id: 'typescript',\n name: 'TypeScript',\n extensions: ['.ts', '.tsx', '.mts', '.cts'],\n icon: 'TS',\n },\n {\n id: 'javascript',\n name: 'JavaScript',\n extensions: ['.js', '.jsx', '.mjs', '.cjs'],\n icon: 'JS',\n },\n {\n id: 'python',\n name: 'Python',\n extensions: ['.py', '.pyi'],\n icon: 'PY',\n },\n {\n id: 'go',\n name: 'Go',\n extensions: ['.go'],\n icon: 'GO',\n },\n {\n id: 'rust',\n name: 'Rust',\n extensions: ['.rs'],\n icon: 'RS',\n },\n {\n id: 'java',\n name: 'Java',\n extensions: ['.java'],\n icon: 'JV',\n },\n {\n id: 'csharp',\n name: 'C#',\n extensions: ['.cs'],\n icon: 'C#',\n },\n {\n id: 'ruby',\n name: 'Ruby',\n extensions: ['.rb'],\n icon: 'RB',\n },\n {\n id: 'php',\n name: 'PHP',\n extensions: ['.php'],\n icon: 'PHP',\n },\n];\n","import type { LensMetadata, LensCategory, Language, CategoryConfig, LanguageConfig, ColorMode, LensColorMode, ColorModeConfig, ColorScheme } from './types.js';\nimport { LENS_REGISTRY, CATEGORY_CONFIGS, LANGUAGE_CONFIGS } from './registry.js';\n\n// ============================================================\n// Lens Lookups\n// ============================================================\n\n/**\n * Get lens metadata by ID\n */\nexport function getLensById(id: string): LensMetadata | undefined {\n return LENS_REGISTRY.find((lens) => lens.id === id);\n}\n\n/**\n * Get all lenses in a category\n */\nexport function getLensesByCategory(category: LensCategory): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.category === category);\n}\n\n/**\n * Get all lenses that support a language\n */\nexport function getLensesByLanguage(language: Language): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.languages.includes(language));\n}\n\n/**\n * Get lenses that support a category for a specific language\n */\nexport function getLensesByCategoryAndLanguage(\n category: LensCategory,\n language: Language\n): LensMetadata[] {\n return LENS_REGISTRY.filter(\n (lens) => lens.category === category && lens.languages.includes(language)\n );\n}\n\n/**\n * Get the category for a lens ID\n */\nexport function getCategoryForLens(lensId: string): LensCategory | undefined {\n return getLensById(lensId)?.category;\n}\n\n/**\n * Get alternative lenses for a given lens ID\n */\nexport function getAlternatives(lensId: string): LensMetadata[] {\n const lens = getLensById(lensId);\n if (!lens) return [];\n\n // Find lenses that list this one as an alternative\n const listedAsAlternative = LENS_REGISTRY.filter(\n (other) => other.alternativeTo?.includes(lensId)\n );\n\n // Find lenses that this one lists as alternatives\n const thisListsAsAlternative = lens.alternativeTo\n ? LENS_REGISTRY.filter((other) => lens.alternativeTo!.includes(other.id))\n : [];\n\n // Combine and dedupe\n const all = [...listedAsAlternative, ...thisListsAsAlternative];\n return Array.from(new Map(all.map((l) => [l.id, l])).values());\n}\n\n/**\n * Check if two lenses are alternatives to each other\n */\nexport function areLensesAlternatives(lensId1: string, lensId2: string): boolean {\n const lens1 = getLensById(lensId1);\n const lens2 = getLensById(lensId2);\n\n if (!lens1 || !lens2) return false;\n if (lens1.category !== lens2.category) return false;\n\n return (\n lens1.alternativeTo?.includes(lensId2) ||\n lens2.alternativeTo?.includes(lensId1) ||\n false\n );\n}\n\n/**\n * Get all lenses that output file metrics (for File City visualization)\n */\nexport function getLensesWithFileMetrics(): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.outputsFileMetrics);\n}\n\n/**\n * Get all lenses that output aggregate scores (for Quality Hexagon)\n */\nexport function getLensesWithAggregates(): LensMetadata[] {\n return LENS_REGISTRY.filter((lens) => lens.outputsAggregate);\n}\n\n// ============================================================\n// Color Mode Helpers (for File City)\n// ============================================================\n\n/**\n * Get the appropriate color mode (lens ID) for a category based on which lenses ran\n * Returns the first lens that ran for the category, preferring alternatives in order\n */\nexport function getColorModeForCategory(\n category: LensCategory,\n lensesRan: string[]\n): string | null {\n const lensesInCategory = getLensesByCategory(category);\n\n // Find the first lens that ran\n for (const lensId of lensesRan) {\n if (lensesInCategory.some((lens) => lens.id === lensId)) {\n return lensId;\n }\n }\n\n return null;\n}\n\n/**\n * Get display name for a lens (for UI labels)\n */\nexport function getLensDisplayName(lensId: string): string {\n return getLensById(lensId)?.name ?? lensId;\n}\n\n/**\n * Get color scheme for a lens (for File City layer rendering)\n */\nexport function getLensColorScheme(lensId: string): 'issues' | 'coverage' | 'binary' {\n return getLensById(lensId)?.colorScheme ?? 'issues';\n}\n\n// ============================================================\n// Category Helpers\n// ============================================================\n\n/**\n * Get category configuration\n */\nexport function getCategoryConfig(category: LensCategory): CategoryConfig | undefined {\n return CATEGORY_CONFIGS.find((c) => c.id === category);\n}\n\n/**\n * Get category display name\n */\nexport function getCategoryDisplayName(category: LensCategory): string {\n return getCategoryConfig(category)?.name ?? category;\n}\n\n/**\n * Check if a category uses inverted scale (lower is better)\n */\nexport function isCategoryInverted(category: LensCategory): boolean {\n return getCategoryConfig(category)?.invertedScale ?? false;\n}\n\n// ============================================================\n// Language Helpers\n// ============================================================\n\n/**\n * Get language configuration\n */\nexport function getLanguageConfig(language: Language): LanguageConfig | undefined {\n return LANGUAGE_CONFIGS.find((l) => l.id === language);\n}\n\n/**\n * Detect language from file extension\n */\nexport function detectLanguageFromExtension(extension: string): Language | undefined {\n const normalizedExt = extension.startsWith('.') ? extension : `.${extension}`;\n const config = LANGUAGE_CONFIGS.find((l) =>\n l.extensions.includes(normalizedExt.toLowerCase())\n );\n return config?.id;\n}\n\n/**\n * Get all languages that have lenses in a category\n */\nexport function getLanguagesForCategory(category: LensCategory): Language[] {\n const lenses = getLensesByCategory(category);\n const languages = new Set<Language>();\n for (const lens of lenses) {\n for (const lang of lens.languages) {\n languages.add(lang);\n }\n }\n return Array.from(languages);\n}\n\n// ============================================================\n// Hexagon Metric Helpers (for Quality Hexagon UI)\n// ============================================================\n\n/**\n * Hexagon metric keys use camelCase (from QualityMetrics interface)\n * These map to LensCategory which uses kebab-case\n */\nexport type HexagonMetricKey =\n | 'linting'\n | 'formatting'\n | 'types'\n | 'tests'\n | 'deadCode'\n | 'documentation';\n\n/**\n * Map hexagon metric keys to registry LensCategory\n */\nconst HEXAGON_METRIC_TO_CATEGORY: Record<HexagonMetricKey, LensCategory> = {\n linting: 'linting',\n formatting: 'formatting',\n types: 'types',\n tests: 'tests',\n deadCode: 'dead-code',\n documentation: 'documentation',\n};\n\n/**\n * Map LensCategory back to hexagon metric keys\n */\nconst CATEGORY_TO_HEXAGON_METRIC: Partial<Record<LensCategory, HexagonMetricKey>> = {\n 'linting': 'linting',\n 'formatting': 'formatting',\n 'types': 'types',\n 'tests': 'tests',\n 'dead-code': 'deadCode',\n 'documentation': 'documentation',\n};\n\n/**\n * Get the LensCategory for a hexagon metric key\n */\nexport function getCategoryForHexagonMetric(metric: HexagonMetricKey): LensCategory {\n return HEXAGON_METRIC_TO_CATEGORY[metric];\n}\n\n/**\n * Get the hexagon metric key for a LensCategory\n */\nexport function getHexagonMetricForCategory(category: LensCategory): HexagonMetricKey | undefined {\n return CATEGORY_TO_HEXAGON_METRIC[category];\n}\n\n/**\n * Check if a lens ID belongs to a hexagon metric\n */\nexport function isLensInHexagonMetric(lensId: string, metric: HexagonMetricKey): boolean {\n const lensCategory = getCategoryForLens(lensId);\n if (!lensCategory) return false;\n return HEXAGON_METRIC_TO_CATEGORY[metric] === lensCategory;\n}\n\n/**\n * Get the color mode for a hexagon metric based on which lenses ran.\n * This is the main entry point for the QualityHexagon panel.\n */\nexport function getColorModeForHexagonMetric(\n metric: HexagonMetricKey,\n lensesRan: string[]\n): string | null {\n const category = HEXAGON_METRIC_TO_CATEGORY[metric];\n return getColorModeForCategory(category, lensesRan);\n}\n\n/**\n * Check if a hexagon metric is configured (has at least one lens that ran)\n */\nexport function isHexagonMetricConfigured(\n metric: HexagonMetricKey,\n lensesRan: string[] | undefined\n): boolean {\n // undefined = old data without lensesRan tracking, assume all configured (backwards compatibility)\n if (lensesRan === undefined) {\n return true;\n }\n // Empty array = new data, explicitly no lenses ran for this package\n if (lensesRan.length === 0) {\n return false;\n }\n return lensesRan.some((lensId) => isLensInHexagonMetric(lensId, metric));\n}\n\n/**\n * Get all hexagon metric keys\n */\nexport function getHexagonMetricKeys(): HexagonMetricKey[] {\n return Object.keys(HEXAGON_METRIC_TO_CATEGORY) as HexagonMetricKey[];\n}\n\n// ============================================================\n// Validation Helpers\n// ============================================================\n\n/**\n * Validate that a lens ID exists in the registry\n */\nexport function isValidLensId(lensId: string): boolean {\n return getLensById(lensId) !== undefined;\n}\n\n/**\n * Find lenses that ran for the same category (potential conflicts)\n */\nexport function findCategoryConflicts(\n lensesRan: string[]\n): Array<{ category: LensCategory; lenses: string[] }> {\n const byCategory = new Map<LensCategory, string[]>();\n\n for (const lensId of lensesRan) {\n const category = getCategoryForLens(lensId);\n if (category) {\n const existing = byCategory.get(category) || [];\n existing.push(lensId);\n byCategory.set(category, existing);\n }\n }\n\n const conflicts: Array<{ category: LensCategory; lenses: string[] }> = [];\n for (const [category, lenses] of byCategory) {\n if (lenses.length > 1) {\n conflicts.push({ category, lenses });\n }\n }\n\n return conflicts;\n}\n\n/**\n * Check if all required lenses produced expected outputs\n */\nexport function validateLensOutputs(\n lensesRan: string[],\n fileMetricsProduced: string[],\n aggregatesProduced: string[]\n): Array<{ lensId: string; missing: ('fileMetrics' | 'aggregate')[] }> {\n const issues: Array<{ lensId: string; missing: ('fileMetrics' | 'aggregate')[] }> = [];\n\n for (const lensId of lensesRan) {\n const lens = getLensById(lensId);\n if (!lens) continue;\n\n const missing: ('fileMetrics' | 'aggregate')[] = [];\n\n if (lens.outputsFileMetrics && !fileMetricsProduced.includes(lensId)) {\n missing.push('fileMetrics');\n }\n if (lens.outputsAggregate && !aggregatesProduced.includes(lensId)) {\n missing.push('aggregate');\n }\n\n if (missing.length > 0) {\n issues.push({ lensId, missing });\n }\n }\n\n return issues;\n}\n\n// ============================================================\n// Color Mode Helpers (for File City visualization)\n// ============================================================\n\n/**\n * Built-in color modes that don't come from quality lenses\n */\nconst BUILT_IN_COLOR_MODES: ColorModeConfig[] = [\n {\n id: 'fileTypes',\n name: 'File Types',\n description: 'Color by file extension/type',\n icon: 'FileCode',\n colorScheme: 'categorical',\n isBuiltIn: true,\n },\n {\n id: 'git',\n name: 'Git Status',\n description: 'Color by git status (modified, added, etc.)',\n icon: 'GitBranch',\n colorScheme: 'categorical',\n isBuiltIn: true,\n },\n];\n\n/**\n * Get all available color modes (built-in + lens-based)\n */\nexport function getAvailableColorModes(): ColorMode[] {\n const builtIn: ColorMode[] = ['fileTypes', 'git'];\n const lensColorModes = getLensColorModes();\n return [...builtIn, ...lensColorModes];\n}\n\n/**\n * Get all lens-based color modes (lenses that output file metrics)\n */\nexport function getLensColorModes(): LensColorMode[] {\n return LENS_REGISTRY\n .filter((lens) => lens.outputsFileMetrics)\n .map((lens) => lens.id as LensColorMode);\n}\n\n/**\n * Check if a string is a valid color mode\n */\nexport function isValidColorMode(mode: string): mode is ColorMode {\n return getAvailableColorModes().includes(mode as ColorMode);\n}\n\n/**\n * Check if a color mode is lens-based (not built-in)\n */\nexport function isLensColorMode(mode: string): mode is LensColorMode {\n return getLensColorModes().includes(mode as LensColorMode);\n}\n\n/**\n * Get configuration for a color mode\n */\nexport function getColorModeConfig(mode: ColorMode): ColorModeConfig | undefined {\n // Check built-in modes first\n const builtIn = BUILT_IN_COLOR_MODES.find((m) => m.id === mode);\n if (builtIn) return builtIn;\n\n // Check lens-based modes\n const lens = getLensById(mode);\n if (lens && lens.outputsFileMetrics) {\n const category = getCategoryConfig(lens.category);\n return {\n id: mode,\n name: lens.name,\n description: lens.description ?? `${lens.name} analysis`,\n icon: category?.icon,\n colorScheme: lens.colorScheme,\n isBuiltIn: false,\n category: lens.category,\n };\n }\n\n return undefined;\n}\n\n/**\n * Get all color mode configurations (for building UI dropdowns/lists)\n */\nexport function getAllColorModeConfigs(): ColorModeConfig[] {\n const configs: ColorModeConfig[] = [...BUILT_IN_COLOR_MODES];\n\n for (const lens of LENS_REGISTRY) {\n if (lens.outputsFileMetrics) {\n const category = getCategoryConfig(lens.category);\n configs.push({\n id: lens.id as ColorMode,\n name: lens.name,\n description: lens.description ?? `${lens.name} analysis`,\n icon: category?.icon,\n colorScheme: lens.colorScheme,\n isBuiltIn: false,\n category: lens.category,\n });\n }\n }\n\n return configs;\n}\n\n/**\n * Get color modes available for a specific language\n * (built-in modes + lens modes that support the language)\n */\nexport function getColorModesForLanguage(language: Language): ColorMode[] {\n const builtIn: ColorMode[] = ['fileTypes', 'git'];\n\n const lensColorModes = LENS_REGISTRY\n .filter((lens) => lens.outputsFileMetrics && lens.languages.includes(language))\n .map((lens) => lens.id as LensColorMode);\n\n return [...builtIn, ...lensColorModes];\n}\n\n/**\n * Get color modes available based on which lenses ran\n * (built-in modes + lens modes from lensesRan list)\n */\nexport function getAvailableColorModesFromLenses(lensesRan: string[]): ColorMode[] {\n const builtIn: ColorMode[] = ['fileTypes', 'git'];\n\n const lensColorModes = lensesRan.filter((lensId) => {\n const lens = getLensById(lensId);\n return lens?.outputsFileMetrics;\n }) as LensColorMode[];\n\n return [...builtIn, ...lensColorModes];\n}\n\n/**\n * Check if a color mode is available based on which lenses ran\n */\nexport function isColorModeAvailable(mode: ColorMode, lensesRan: string[]): boolean {\n // Built-in modes are always available\n if (mode === 'fileTypes' || mode === 'git') {\n return true;\n }\n\n // Lens-based modes are available if the lens ran\n return lensesRan.includes(mode);\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@principal-ai/quality-lens-registry",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Centralized registry of quality lens metadata for the Principal AI quality toolchain",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",