feat: subcomando project en CLI con busqueda y listado integrado
Añade cmd/fn/project.go con subcomandos init, list, show y status para gestionar proyectos desde la CLI. Integra projects en fn search, fn list y fn show para que aparezcan junto a functions, types y apps. También añade soporte para vaults en fn show y template project en fn add -k project.
This commit is contained in:
+84
-4
@@ -37,6 +37,8 @@ func main() {
|
||||
cmdRun(os.Args[2:])
|
||||
case "check":
|
||||
cmdCheck(os.Args[2:])
|
||||
case "project":
|
||||
cmdProject(os.Args[2:])
|
||||
case "app":
|
||||
cmdApp(os.Args[2:])
|
||||
case "analysis":
|
||||
@@ -63,6 +65,7 @@ Usage:
|
||||
fn check params Lista funciones sin params_schema
|
||||
fn ops <subcommand> Gestiona operations.db (fn ops help)
|
||||
fn proposal <add|list|show|update> Gestiona proposals
|
||||
fn project <init|list|show|status> Gestiona proyectos
|
||||
fn app <list|clone|pull> Gestiona apps externas (Gitea)
|
||||
fn analysis <list|clone|pull> Gestiona analyses externas (Gitea)`)
|
||||
}
|
||||
@@ -126,7 +129,8 @@ func cmdIndex() {
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Indexed %d functions, %d types, %d apps, %d analysis, %d unit_tests\n", result.Functions, result.Types, result.Apps, result.Analysis, result.UnitTests)
|
||||
fmt.Printf("Indexed %d functions, %d types, %d apps, %d analysis, %d projects, %d vaults, %d unit_tests\n",
|
||||
result.Functions, result.Types, result.Apps, result.Analysis, result.Projects, result.Vaults, result.UnitTests)
|
||||
for _, e := range result.ValidationErrors {
|
||||
fmt.Fprintf(os.Stderr, " INVALID: %s\n", e)
|
||||
}
|
||||
@@ -190,7 +194,13 @@ func cmdSearch(args []string) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if len(fns) == 0 && len(types) == 0 && len(apps) == 0 && len(analyses) == 0 {
|
||||
projects, err := db.SearchProjects(query)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if len(fns) == 0 && len(types) == 0 && len(apps) == 0 && len(analyses) == 0 && len(projects) == 0 {
|
||||
fmt.Println("No results.")
|
||||
return
|
||||
}
|
||||
@@ -233,6 +243,16 @@ func cmdSearch(args []string) {
|
||||
fmt.Fprintf(w, "analysis\t%s\t%s\t%s\n", a.ID, a.Lang, desc)
|
||||
}
|
||||
}
|
||||
if len(projects) > 0 {
|
||||
if len(fns) > 0 || len(types) > 0 || len(apps) > 0 || len(analyses) > 0 {
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
fmt.Fprintln(w, "PROJECT\tID\tDESCRIPTION")
|
||||
for _, p := range projects {
|
||||
desc := truncate(p.Description, 60)
|
||||
fmt.Fprintf(w, "project\t%s\t%s\n", p.ID, desc)
|
||||
}
|
||||
}
|
||||
w.Flush()
|
||||
}
|
||||
|
||||
@@ -317,7 +337,22 @@ func cmdList(args []string) {
|
||||
fmt.Fprintf(w, "analysis\t%s\t%s\t%s\n", a.ID, a.Lang, a.Domain)
|
||||
}
|
||||
}
|
||||
if len(fns) == 0 && len(types) == 0 && len(apps) == 0 && len(analyses) == 0 {
|
||||
projects, err := db.ListAllProjects()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if len(projects) > 0 {
|
||||
if len(fns) > 0 || len(types) > 0 || len(apps) > 0 || len(analyses) > 0 {
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
fmt.Fprintln(w, "PROJECT\tID\tDESCRIPTION")
|
||||
for _, p := range projects {
|
||||
fmt.Fprintf(w, "project\t%s\t%s\n", p.ID, truncate(p.Description, 60))
|
||||
}
|
||||
}
|
||||
if len(fns) == 0 && len(types) == 0 && len(apps) == 0 && len(analyses) == 0 && len(projects) == 0 {
|
||||
fmt.Println("Registry is empty. Run 'fn index' first.")
|
||||
}
|
||||
w.Flush()
|
||||
@@ -359,6 +394,18 @@ func cmdShow(args []string) {
|
||||
return
|
||||
}
|
||||
|
||||
p, errP := db.GetProject(id)
|
||||
if errP == nil {
|
||||
printProjectEntry(p)
|
||||
return
|
||||
}
|
||||
|
||||
v, errV := db.GetVault(id)
|
||||
if errV == nil {
|
||||
printVaultEntry(v)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "not found: %s\n", id)
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -518,6 +565,37 @@ func printAnalysisEntry(a *registry.Analysis) {
|
||||
}
|
||||
}
|
||||
|
||||
func printProjectEntry(p *registry.Project) {
|
||||
fmt.Printf("ID: %s\n", p.ID)
|
||||
fmt.Printf("Name: %s\n", p.Name)
|
||||
fmt.Printf("Description: %s\n", p.Description)
|
||||
fmt.Printf("Tags: %s\n", strings.Join(p.Tags, ", "))
|
||||
fmt.Printf("Dir: %s\n", p.DirPath)
|
||||
if p.RepoURL != "" {
|
||||
fmt.Printf("Repo URL: %s\n", p.RepoURL)
|
||||
}
|
||||
if p.Notes != "" {
|
||||
fmt.Printf("\nNotes:\n%s\n", p.Notes)
|
||||
}
|
||||
if p.Documentation != "" {
|
||||
fmt.Printf("\nDocumentation:\n%s\n", p.Documentation)
|
||||
}
|
||||
}
|
||||
|
||||
func printVaultEntry(v *registry.Vault) {
|
||||
fmt.Printf("ID: %s\n", v.ID)
|
||||
fmt.Printf("Name: %s\n", v.Name)
|
||||
if v.ProjectID != "" {
|
||||
fmt.Printf("Project: %s\n", v.ProjectID)
|
||||
}
|
||||
fmt.Printf("Description: %s\n", v.Description)
|
||||
if v.Path != "" {
|
||||
fmt.Printf("Path: %s\n", v.Path)
|
||||
}
|
||||
fmt.Printf("Symlink: %v\n", v.Symlink)
|
||||
fmt.Printf("Tags: %s\n", strings.Join(v.Tags, ", "))
|
||||
}
|
||||
|
||||
// --- check ---
|
||||
|
||||
func cmdCheck(args []string) {
|
||||
@@ -594,8 +672,10 @@ func cmdAdd(args []string) {
|
||||
templatePath = filepath.Join(r, "docs", "templates", "app.md")
|
||||
case "analysis":
|
||||
templatePath = filepath.Join(r, "docs", "templates", "analysis.md")
|
||||
case "project":
|
||||
templatePath = filepath.Join(r, "docs", "templates", "project.md")
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "unknown kind: %s (use function, pipeline, component, app, or analysis)\n", kind)
|
||||
fmt.Fprintf(os.Stderr, "unknown kind: %s (use function, pipeline, component, app, analysis, or project)\n", kind)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user