Manages integration catalog fetching, caching, and searching.
| 54 | # --------------------------------------------------------------------------- |
| 55 | |
| 56 | class IntegrationCatalog(CatalogStackBase): |
| 57 | """Manages integration catalog fetching, caching, and searching.""" |
| 58 | |
| 59 | DEFAULT_CATALOG_URL = ( |
| 60 | "https://raw.githubusercontent.com/github/spec-kit/main/integrations/catalog.json" |
| 61 | ) |
| 62 | COMMUNITY_CATALOG_URL = ( |
| 63 | "https://raw.githubusercontent.com/github/spec-kit/main/integrations/catalog.community.json" |
| 64 | ) |
| 65 | CACHE_DURATION = 3600 # 1 hour |
| 66 | CONFIG_FILENAME = "integration-catalogs.yml" |
| 67 | ENTRY_CLASS = IntegrationCatalogEntry |
| 68 | ERROR_TYPE = IntegrationCatalogError |
| 69 | VALIDATION_ERROR_TYPE = IntegrationValidationError |
| 70 | |
| 71 | def __init__(self, project_root: Path) -> None: |
| 72 | self.project_root = project_root |
| 73 | self.cache_dir = project_root / ".specify" / "integrations" / ".cache" |
| 74 | |
| 75 | def get_active_catalogs(self) -> List[IntegrationCatalogEntry]: |
| 76 | """Return the ordered list of active integration catalogs. |
| 77 | |
| 78 | Resolution: |
| 79 | 1. ``SPECKIT_INTEGRATION_CATALOG_URL`` env var |
| 80 | 2. Project ``.specify/integration-catalogs.yml`` |
| 81 | 3. User ``~/.specify/integration-catalogs.yml`` |
| 82 | 4. Built-in defaults (built-in + community) |
| 83 | """ |
| 84 | import sys |
| 85 | |
| 86 | env_value = os.environ.get("SPECKIT_INTEGRATION_CATALOG_URL", "").strip() |
| 87 | if env_value: |
| 88 | self._validate_catalog_url(env_value) |
| 89 | if env_value != self.DEFAULT_CATALOG_URL: |
| 90 | if not getattr(self, "_non_default_catalog_warning_shown", False): |
| 91 | print( |
| 92 | "Warning: Using non-default integration catalog. " |
| 93 | "Only use catalogs from sources you trust.", |
| 94 | file=sys.stderr, |
| 95 | ) |
| 96 | self._non_default_catalog_warning_shown = True |
| 97 | return [ |
| 98 | IntegrationCatalogEntry( |
| 99 | url=env_value, |
| 100 | name="custom", |
| 101 | priority=1, |
| 102 | install_allowed=True, |
| 103 | description="Custom catalog via SPECKIT_INTEGRATION_CATALOG_URL", |
| 104 | ) |
| 105 | ] |
| 106 | |
| 107 | project_cfg = self.project_root / ".specify" / self.CONFIG_FILENAME |
| 108 | catalogs = self._load_catalog_config(project_cfg) |
| 109 | if catalogs is not None: |
| 110 | return catalogs |
| 111 | |
| 112 | user_cfg = Path.home() / ".specify" / self.CONFIG_FILENAME |
| 113 | catalogs = self._load_catalog_config(user_cfg) |
no outgoing calls