|
1
|
"""Template registry — loads and queries templates.yaml.""" |
|
2
|
|
|
3
|
from __future__ import annotations |
|
4
|
|
|
5
|
from pathlib import Path |
|
6
|
from typing import Literal |
|
7
|
|
|
8
|
import yaml |
|
9
|
from pydantic import BaseModel, Field |
|
10
|
|
|
11
|
_DATA_DIR = Path(__file__).parent / "data" |
|
12
|
|
|
13
|
|
|
14
|
class TemplateInfo(BaseModel): |
|
15
|
"""A single template entry from templates.yaml.""" |
|
16
|
|
|
17
|
name: str |
|
18
|
repo: str |
|
19
|
size: Literal["full", "micro", "edge"] |
|
20
|
language: str |
|
21
|
backend: str |
|
22
|
frontend: str |
|
23
|
status: Literal["done", "building", "planned"] |
|
24
|
description: str |
|
25
|
topologies: list[str] = Field(default_factory=list) |
|
26
|
best_for: str = "" |
|
27
|
|
|
28
|
|
|
29
|
class Registry: |
|
30
|
"""Loads templates.yaml and provides query methods.""" |
|
31
|
|
|
32
|
def __init__(self, yaml_path: Path | None = None) -> None: |
|
33
|
path = yaml_path or (_DATA_DIR / "templates.yaml") |
|
34
|
raw: list[dict] = yaml.safe_load(path.read_text()) |
|
35
|
self._templates: list[TemplateInfo] = [TemplateInfo(**entry) for entry in raw] |
|
36
|
|
|
37
|
def list_all(self) -> list[TemplateInfo]: |
|
38
|
"""Return all templates.""" |
|
39
|
return list(self._templates) |
|
40
|
|
|
41
|
def filter_by_size(self, size: str) -> list[TemplateInfo]: |
|
42
|
"""Return templates matching the given size.""" |
|
43
|
return [t for t in self._templates if t.size == size] |
|
44
|
|
|
45
|
def filter_by_language(self, language: str) -> list[TemplateInfo]: |
|
46
|
"""Return templates matching the given language.""" |
|
47
|
return [t for t in self._templates if t.language == language] |
|
48
|
|
|
49
|
def filter_by_status(self, status: str) -> list[TemplateInfo]: |
|
50
|
"""Return templates matching the given status.""" |
|
51
|
return [t for t in self._templates if t.status == status] |
|
52
|
|
|
53
|
def get_by_name(self, name: str) -> TemplateInfo | None: |
|
54
|
"""Return the template with the given name, or None.""" |
|
55
|
for t in self._templates: |
|
56
|
if t.name == name: |
|
57
|
return t |
|
58
|
return None |
|
59
|
|
|
60
|
def search(self, query: str) -> list[TemplateInfo]: |
|
61
|
"""Return templates whose name, description, or best_for contains the query (case-insensitive).""" |
|
62
|
q = query.lower() |
|
63
|
return [ |
|
64
|
t for t in self._templates if q in t.name.lower() or q in t.description.lower() or q in t.best_for.lower() |
|
65
|
] |
|
66
|
|
|
67
|
def names(self) -> list[str]: |
|
68
|
"""Return all template names.""" |
|
69
|
return [t.name for t in self._templates] |
|
70
|
|