feat: tabla apps en registry — modelo, parser, indexer y CLI
Agrega soporte completo para indexar aplicaciones del directorio apps/. Cada app tiene un descriptor app.md con frontmatter YAML que el indexer recoge automaticamente. Incluye migracion 004, modelo App, ParseAppMD, ValidateApp, store CRUD con FTS5, y soporte en fn list/search/show. Crea descriptores app.md para docker_tui, pipeline_launcher y metabase_registry.
This commit is contained in:
@@ -54,6 +54,20 @@ type rawType struct {
|
||||
FilePath string `yaml:"file_path"`
|
||||
}
|
||||
|
||||
// rawApp mirrors the YAML frontmatter of an app .md file.
|
||||
type rawApp struct {
|
||||
Name string `yaml:"name"`
|
||||
Lang string `yaml:"lang"`
|
||||
Domain string `yaml:"domain"`
|
||||
Description string `yaml:"description"`
|
||||
Tags []string `yaml:"tags"`
|
||||
UsesFunctions []string `yaml:"uses_functions"`
|
||||
UsesTypes []string `yaml:"uses_types"`
|
||||
Framework string `yaml:"framework"`
|
||||
EntryPoint string `yaml:"entry_point"`
|
||||
DirPath string `yaml:"dir_path"`
|
||||
}
|
||||
|
||||
// extractFrontmatter splits a .md file into YAML frontmatter and body.
|
||||
func extractFrontmatter(data []byte) ([]byte, []byte, error) {
|
||||
content := data
|
||||
@@ -198,6 +212,51 @@ func ParseTypeMD(path string, root string) (*Type, error) {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// ParseAppMD parses an app .md file into an App.
|
||||
func ParseAppMD(path string, root string) (*App, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading %s: %w", path, err)
|
||||
}
|
||||
|
||||
fm, body, err := extractFrontmatter(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing %s: %w", path, err)
|
||||
}
|
||||
|
||||
var raw rawApp
|
||||
if err := yaml.Unmarshal(fm, &raw); err != nil {
|
||||
return nil, fmt.Errorf("parsing YAML in %s: %w", path, err)
|
||||
}
|
||||
|
||||
if raw.Name == "" {
|
||||
return nil, fmt.Errorf("%s: name is required", path)
|
||||
}
|
||||
if raw.Description == "" {
|
||||
return nil, fmt.Errorf("%s: description is required", path)
|
||||
}
|
||||
|
||||
sections := extractSections(body)
|
||||
|
||||
a := &App{
|
||||
ID: GenerateID(raw.Name, raw.Lang, raw.Domain),
|
||||
Name: raw.Name,
|
||||
Lang: raw.Lang,
|
||||
Domain: raw.Domain,
|
||||
Description: raw.Description,
|
||||
Tags: raw.Tags,
|
||||
UsesFunctions: raw.UsesFunctions,
|
||||
UsesTypes: raw.UsesTypes,
|
||||
Framework: raw.Framework,
|
||||
EntryPoint: raw.EntryPoint,
|
||||
Documentation: sections.documentation,
|
||||
Notes: sections.notes,
|
||||
DirPath: raw.DirPath,
|
||||
}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// bodySections holds the extracted sections from a .md body.
|
||||
type bodySections struct {
|
||||
example string // content under ## Ejemplo
|
||||
|
||||
Reference in New Issue
Block a user