@principal-ai/quality-lens-registry 0.1.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,14 +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,
35
+ getCategoryForHexagonMetric: () => getCategoryForHexagonMetric,
32
36
  getCategoryForLens: () => getCategoryForLens,
37
+ getColorModeConfig: () => getColorModeConfig,
33
38
  getColorModeForCategory: () => getColorModeForCategory,
39
+ getColorModeForHexagonMetric: () => getColorModeForHexagonMetric,
40
+ getColorModesForLanguage: () => getColorModesForLanguage,
41
+ getHexagonMetricForCategory: () => getHexagonMetricForCategory,
42
+ getHexagonMetricKeys: () => getHexagonMetricKeys,
34
43
  getLanguageConfig: () => getLanguageConfig,
35
44
  getLanguagesForCategory: () => getLanguagesForCategory,
36
45
  getLensById: () => getLensById,
46
+ getLensColorModes: () => getLensColorModes,
37
47
  getLensColorScheme: () => getLensColorScheme,
38
48
  getLensDisplayName: () => getLensDisplayName,
39
49
  getLensesByCategory: () => getLensesByCategory,
@@ -42,6 +52,11 @@ __export(index_exports, {
42
52
  getLensesWithAggregates: () => getLensesWithAggregates,
43
53
  getLensesWithFileMetrics: () => getLensesWithFileMetrics,
44
54
  isCategoryInverted: () => isCategoryInverted,
55
+ isColorModeAvailable: () => isColorModeAvailable,
56
+ isHexagonMetricConfigured: () => isHexagonMetricConfigured,
57
+ isLensColorMode: () => isLensColorMode,
58
+ isLensInHexagonMetric: () => isLensInHexagonMetric,
59
+ isValidColorMode: () => isValidColorMode,
45
60
  isValidLensId: () => isValidLensId,
46
61
  validateLensOutputs: () => validateLensOutputs
47
62
  });
@@ -608,6 +623,49 @@ function getLanguagesForCategory(category) {
608
623
  }
609
624
  return Array.from(languages);
610
625
  }
626
+ var HEXAGON_METRIC_TO_CATEGORY = {
627
+ linting: "linting",
628
+ formatting: "formatting",
629
+ types: "types",
630
+ tests: "tests",
631
+ deadCode: "dead-code",
632
+ documentation: "documentation"
633
+ };
634
+ var CATEGORY_TO_HEXAGON_METRIC = {
635
+ "linting": "linting",
636
+ "formatting": "formatting",
637
+ "types": "types",
638
+ "tests": "tests",
639
+ "dead-code": "deadCode",
640
+ "documentation": "documentation"
641
+ };
642
+ function getCategoryForHexagonMetric(metric) {
643
+ return HEXAGON_METRIC_TO_CATEGORY[metric];
644
+ }
645
+ function getHexagonMetricForCategory(category) {
646
+ return CATEGORY_TO_HEXAGON_METRIC[category];
647
+ }
648
+ function isLensInHexagonMetric(lensId, metric) {
649
+ const lensCategory = getCategoryForLens(lensId);
650
+ if (!lensCategory) return false;
651
+ return HEXAGON_METRIC_TO_CATEGORY[metric] === lensCategory;
652
+ }
653
+ function getColorModeForHexagonMetric(metric, lensesRan) {
654
+ const category = HEXAGON_METRIC_TO_CATEGORY[metric];
655
+ return getColorModeForCategory(category, lensesRan);
656
+ }
657
+ function isHexagonMetricConfigured(metric, lensesRan) {
658
+ if (lensesRan === void 0) {
659
+ return true;
660
+ }
661
+ if (lensesRan.length === 0) {
662
+ return false;
663
+ }
664
+ return lensesRan.some((lensId) => isLensInHexagonMetric(lensId, metric));
665
+ }
666
+ function getHexagonMetricKeys() {
667
+ return Object.keys(HEXAGON_METRIC_TO_CATEGORY);
668
+ }
611
669
  function isValidLensId(lensId) {
612
670
  return getLensById(lensId) !== void 0;
613
671
  }
@@ -647,6 +705,93 @@ function validateLensOutputs(lensesRan, fileMetricsProduced, aggregatesProduced)
647
705
  }
648
706
  return issues;
649
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
+ }
650
795
  // Annotate the CommonJS export names for ESM import in node:
651
796
  0 && (module.exports = {
652
797
  CATEGORY_CONFIGS,
@@ -655,14 +800,24 @@ function validateLensOutputs(lensesRan, fileMetricsProduced, aggregatesProduced)
655
800
  areLensesAlternatives,
656
801
  detectLanguageFromExtension,
657
802
  findCategoryConflicts,
803
+ getAllColorModeConfigs,
658
804
  getAlternatives,
805
+ getAvailableColorModes,
806
+ getAvailableColorModesFromLenses,
659
807
  getCategoryConfig,
660
808
  getCategoryDisplayName,
809
+ getCategoryForHexagonMetric,
661
810
  getCategoryForLens,
811
+ getColorModeConfig,
662
812
  getColorModeForCategory,
813
+ getColorModeForHexagonMetric,
814
+ getColorModesForLanguage,
815
+ getHexagonMetricForCategory,
816
+ getHexagonMetricKeys,
663
817
  getLanguageConfig,
664
818
  getLanguagesForCategory,
665
819
  getLensById,
820
+ getLensColorModes,
666
821
  getLensColorScheme,
667
822
  getLensDisplayName,
668
823
  getLensesByCategory,
@@ -671,6 +826,11 @@ function validateLensOutputs(lensesRan, fileMetricsProduced, aggregatesProduced)
671
826
  getLensesWithAggregates,
672
827
  getLensesWithFileMetrics,
673
828
  isCategoryInverted,
829
+ isColorModeAvailable,
830
+ isHexagonMetricConfigured,
831
+ isLensColorMode,
832
+ isLensInHexagonMetric,
833
+ isValidColorMode,
674
834
  isValidLensId,
675
835
  validateLensOutputs
676
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 // 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// 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
@@ -158,6 +187,36 @@ declare function detectLanguageFromExtension(extension: string): Language | unde
158
187
  * Get all languages that have lenses in a category
159
188
  */
160
189
  declare function getLanguagesForCategory(category: LensCategory): Language[];
190
+ /**
191
+ * Hexagon metric keys use camelCase (from QualityMetrics interface)
192
+ * These map to LensCategory which uses kebab-case
193
+ */
194
+ type HexagonMetricKey = 'linting' | 'formatting' | 'types' | 'tests' | 'deadCode' | 'documentation';
195
+ /**
196
+ * Get the LensCategory for a hexagon metric key
197
+ */
198
+ declare function getCategoryForHexagonMetric(metric: HexagonMetricKey): LensCategory;
199
+ /**
200
+ * Get the hexagon metric key for a LensCategory
201
+ */
202
+ declare function getHexagonMetricForCategory(category: LensCategory): HexagonMetricKey | undefined;
203
+ /**
204
+ * Check if a lens ID belongs to a hexagon metric
205
+ */
206
+ declare function isLensInHexagonMetric(lensId: string, metric: HexagonMetricKey): boolean;
207
+ /**
208
+ * Get the color mode for a hexagon metric based on which lenses ran.
209
+ * This is the main entry point for the QualityHexagon panel.
210
+ */
211
+ declare function getColorModeForHexagonMetric(metric: HexagonMetricKey, lensesRan: string[]): string | null;
212
+ /**
213
+ * Check if a hexagon metric is configured (has at least one lens that ran)
214
+ */
215
+ declare function isHexagonMetricConfigured(metric: HexagonMetricKey, lensesRan: string[] | undefined): boolean;
216
+ /**
217
+ * Get all hexagon metric keys
218
+ */
219
+ declare function getHexagonMetricKeys(): HexagonMetricKey[];
161
220
  /**
162
221
  * Validate that a lens ID exists in the registry
163
222
  */
@@ -176,5 +235,43 @@ declare function validateLensOutputs(lensesRan: string[], fileMetricsProduced: s
176
235
  lensId: string;
177
236
  missing: ('fileMetrics' | 'aggregate')[];
178
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;
179
276
 
180
- export { CATEGORY_CONFIGS, type CategoryConfig, type ColorScheme, LANGUAGE_CONFIGS, LENS_REGISTRY, type Language, type LanguageConfig, type LensCategory, type LensMetadata, areLensesAlternatives, detectLanguageFromExtension, findCategoryConflicts, getAlternatives, getCategoryConfig, getCategoryDisplayName, getCategoryForLens, getColorModeForCategory, getLanguageConfig, getLanguagesForCategory, getLensById, getLensColorScheme, getLensDisplayName, getLensesByCategory, getLensesByCategoryAndLanguage, getLensesByLanguage, getLensesWithAggregates, getLensesWithFileMetrics, isCategoryInverted, 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
@@ -158,6 +187,36 @@ declare function detectLanguageFromExtension(extension: string): Language | unde
158
187
  * Get all languages that have lenses in a category
159
188
  */
160
189
  declare function getLanguagesForCategory(category: LensCategory): Language[];
190
+ /**
191
+ * Hexagon metric keys use camelCase (from QualityMetrics interface)
192
+ * These map to LensCategory which uses kebab-case
193
+ */
194
+ type HexagonMetricKey = 'linting' | 'formatting' | 'types' | 'tests' | 'deadCode' | 'documentation';
195
+ /**
196
+ * Get the LensCategory for a hexagon metric key
197
+ */
198
+ declare function getCategoryForHexagonMetric(metric: HexagonMetricKey): LensCategory;
199
+ /**
200
+ * Get the hexagon metric key for a LensCategory
201
+ */
202
+ declare function getHexagonMetricForCategory(category: LensCategory): HexagonMetricKey | undefined;
203
+ /**
204
+ * Check if a lens ID belongs to a hexagon metric
205
+ */
206
+ declare function isLensInHexagonMetric(lensId: string, metric: HexagonMetricKey): boolean;
207
+ /**
208
+ * Get the color mode for a hexagon metric based on which lenses ran.
209
+ * This is the main entry point for the QualityHexagon panel.
210
+ */
211
+ declare function getColorModeForHexagonMetric(metric: HexagonMetricKey, lensesRan: string[]): string | null;
212
+ /**
213
+ * Check if a hexagon metric is configured (has at least one lens that ran)
214
+ */
215
+ declare function isHexagonMetricConfigured(metric: HexagonMetricKey, lensesRan: string[] | undefined): boolean;
216
+ /**
217
+ * Get all hexagon metric keys
218
+ */
219
+ declare function getHexagonMetricKeys(): HexagonMetricKey[];
161
220
  /**
162
221
  * Validate that a lens ID exists in the registry
163
222
  */
@@ -176,5 +235,43 @@ declare function validateLensOutputs(lensesRan: string[], fileMetricsProduced: s
176
235
  lensId: string;
177
236
  missing: ('fileMetrics' | 'aggregate')[];
178
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;
179
276
 
180
- export { CATEGORY_CONFIGS, type CategoryConfig, type ColorScheme, LANGUAGE_CONFIGS, LENS_REGISTRY, type Language, type LanguageConfig, type LensCategory, type LensMetadata, areLensesAlternatives, detectLanguageFromExtension, findCategoryConflicts, getAlternatives, getCategoryConfig, getCategoryDisplayName, getCategoryForLens, getColorModeForCategory, getLanguageConfig, getLanguagesForCategory, getLensById, getLensColorScheme, getLensDisplayName, getLensesByCategory, getLensesByCategoryAndLanguage, getLensesByLanguage, getLensesWithAggregates, getLensesWithFileMetrics, isCategoryInverted, 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
@@ -559,6 +559,49 @@ function getLanguagesForCategory(category) {
559
559
  }
560
560
  return Array.from(languages);
561
561
  }
562
+ var HEXAGON_METRIC_TO_CATEGORY = {
563
+ linting: "linting",
564
+ formatting: "formatting",
565
+ types: "types",
566
+ tests: "tests",
567
+ deadCode: "dead-code",
568
+ documentation: "documentation"
569
+ };
570
+ var CATEGORY_TO_HEXAGON_METRIC = {
571
+ "linting": "linting",
572
+ "formatting": "formatting",
573
+ "types": "types",
574
+ "tests": "tests",
575
+ "dead-code": "deadCode",
576
+ "documentation": "documentation"
577
+ };
578
+ function getCategoryForHexagonMetric(metric) {
579
+ return HEXAGON_METRIC_TO_CATEGORY[metric];
580
+ }
581
+ function getHexagonMetricForCategory(category) {
582
+ return CATEGORY_TO_HEXAGON_METRIC[category];
583
+ }
584
+ function isLensInHexagonMetric(lensId, metric) {
585
+ const lensCategory = getCategoryForLens(lensId);
586
+ if (!lensCategory) return false;
587
+ return HEXAGON_METRIC_TO_CATEGORY[metric] === lensCategory;
588
+ }
589
+ function getColorModeForHexagonMetric(metric, lensesRan) {
590
+ const category = HEXAGON_METRIC_TO_CATEGORY[metric];
591
+ return getColorModeForCategory(category, lensesRan);
592
+ }
593
+ function isHexagonMetricConfigured(metric, lensesRan) {
594
+ if (lensesRan === void 0) {
595
+ return true;
596
+ }
597
+ if (lensesRan.length === 0) {
598
+ return false;
599
+ }
600
+ return lensesRan.some((lensId) => isLensInHexagonMetric(lensId, metric));
601
+ }
602
+ function getHexagonMetricKeys() {
603
+ return Object.keys(HEXAGON_METRIC_TO_CATEGORY);
604
+ }
562
605
  function isValidLensId(lensId) {
563
606
  return getLensById(lensId) !== void 0;
564
607
  }
@@ -598,6 +641,93 @@ function validateLensOutputs(lensesRan, fileMetricsProduced, aggregatesProduced)
598
641
  }
599
642
  return issues;
600
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
+ }
601
731
  export {
602
732
  CATEGORY_CONFIGS,
603
733
  LANGUAGE_CONFIGS,
@@ -605,14 +735,24 @@ export {
605
735
  areLensesAlternatives,
606
736
  detectLanguageFromExtension,
607
737
  findCategoryConflicts,
738
+ getAllColorModeConfigs,
608
739
  getAlternatives,
740
+ getAvailableColorModes,
741
+ getAvailableColorModesFromLenses,
609
742
  getCategoryConfig,
610
743
  getCategoryDisplayName,
744
+ getCategoryForHexagonMetric,
611
745
  getCategoryForLens,
746
+ getColorModeConfig,
612
747
  getColorModeForCategory,
748
+ getColorModeForHexagonMetric,
749
+ getColorModesForLanguage,
750
+ getHexagonMetricForCategory,
751
+ getHexagonMetricKeys,
613
752
  getLanguageConfig,
614
753
  getLanguagesForCategory,
615
754
  getLensById,
755
+ getLensColorModes,
616
756
  getLensColorScheme,
617
757
  getLensDisplayName,
618
758
  getLensesByCategory,
@@ -621,6 +761,11 @@ export {
621
761
  getLensesWithAggregates,
622
762
  getLensesWithFileMetrics,
623
763
  isCategoryInverted,
764
+ isColorModeAvailable,
765
+ isHexagonMetricConfigured,
766
+ isLensColorMode,
767
+ isLensInHexagonMetric,
768
+ isValidColorMode,
624
769
  isValidLensId,
625
770
  validateLensOutputs
626
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// 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.1.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",