Files
beads/examples/library-usage/main.go
Steve Yegge 5e7b3aa43a Add Beads library API for Go integration
Expose full Storage interface and all types through public beads.go API,
enabling external Go projects (like VC) to import Beads directly instead
of spawning CLI processes.

Changes:
- Expanded beads.go with all public types (Issue, Dependency, Comment, etc.)
- Added all constants (Status, IssueType, DependencyType, EventType)
- Created comprehensive integration tests (beads_integration_test.go)
- Added library usage example at examples/library-usage/
- Documented library integration in README.md

Test coverage: 96.4% on public API, 14 integration tests, all passing.

Closes bd-58, bd-59

Amp-Thread-ID: https://ampcode.com/threads/T-f0093c79-7422-45e2-b0ed-0ddfebc9ffea
Co-authored-by: Amp <amp@ampcode.com>
2025-10-22 15:49:40 -07:00

130 lines
3.8 KiB
Go

// Package main demonstrates using Beads as a Go library
//
// This example shows how an external project (like VC) can import and use
// Beads programmatically instead of spawning CLI processes.
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/steveyegge/beads"
)
func main() {
ctx := context.Background()
// Find the Beads database (looks for .beads/*.db in current/parent dirs)
dbPath := beads.FindDatabasePath()
if dbPath == "" {
log.Fatal("No Beads database found. Run 'bd init' first.")
}
fmt.Printf("Using database: %s\n\n", dbPath)
// Open the database
store, err := beads.NewSQLiteStorage(dbPath)
if err != nil {
log.Fatalf("Failed to open storage: %v", err)
}
defer store.Close()
// Example 1: Get ready work
fmt.Println("=== Ready Work ===")
ready, err := store.GetReadyWork(ctx, beads.WorkFilter{
Status: beads.StatusOpen,
Limit: 5,
})
if err != nil {
log.Fatalf("Failed to get ready work: %v", err)
}
for _, issue := range ready {
fmt.Printf("- %s: %s (priority %d)\n", issue.ID, issue.Title, issue.Priority)
}
// Example 2: Create an issue
fmt.Println("\n=== Creating Issue ===")
newIssue := &beads.Issue{
ID: "", // Empty = auto-generate
Title: "Example library-created issue",
Description: "This issue was created programmatically using Beads as a library",
Status: beads.StatusOpen,
Priority: 2,
IssueType: beads.TypeTask,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
if err := store.CreateIssue(ctx, newIssue, "library-example"); err != nil {
log.Fatalf("Failed to create issue: %v", err)
}
fmt.Printf("Created issue: %s\n", newIssue.ID)
// Example 3: Add a dependency
fmt.Println("\n=== Adding Dependency ===")
dep := &beads.Dependency{
IssueID: newIssue.ID,
DependsOnID: "bd-1", // Assumes bd-1 exists
Type: beads.DepDiscoveredFrom,
CreatedAt: time.Now(),
CreatedBy: "library-example",
}
if err := store.AddDependency(ctx, dep, "library-example"); err != nil {
// Don't fail if bd-1 doesn't exist
fmt.Printf("Note: Could not add dependency (bd-1 may not exist): %v\n", err)
} else {
fmt.Printf("Added dependency: %s discovered-from bd-1\n", newIssue.ID)
}
// Example 4: Add a label
fmt.Println("\n=== Adding Label ===")
if err := store.AddLabel(ctx, newIssue.ID, "library-usage", "library-example"); err != nil {
log.Fatalf("Failed to add label: %v", err)
}
fmt.Printf("Added label 'library-usage' to %s\n", newIssue.ID)
// Example 5: Add a comment
fmt.Println("\n=== Adding Comment ===")
comment, err := store.AddIssueComment(ctx, newIssue.ID, "library-example", "This is a programmatic comment")
if err != nil {
log.Fatalf("Failed to add comment: %v", err)
}
fmt.Printf("Added comment #%d\n", comment.ID)
// Example 6: Update issue status
fmt.Println("\n=== Updating Status ===")
updates := map[string]interface{}{
"status": beads.StatusInProgress,
}
if err := store.UpdateIssue(ctx, newIssue.ID, updates, "library-example"); err != nil {
log.Fatalf("Failed to update issue: %v", err)
}
fmt.Printf("Updated %s status to in_progress\n", newIssue.ID)
// Example 7: Get statistics
fmt.Println("\n=== Statistics ===")
stats, err := store.GetStatistics(ctx)
if err != nil {
log.Fatalf("Failed to get statistics: %v", err)
}
fmt.Printf("Total issues: %d\n", stats.TotalIssues)
fmt.Printf("Open: %d | In Progress: %d | Closed: %d | Blocked: %d | Ready: %d\n",
stats.OpenIssues, stats.InProgressIssues, stats.ClosedIssues,
stats.BlockedIssues, stats.ReadyIssues)
// Example 8: Close the issue
fmt.Println("\n=== Closing Issue ===")
if err := store.CloseIssue(ctx, newIssue.ID, "Completed demo", "library-example"); err != nil {
log.Fatalf("Failed to close issue: %v", err)
}
fmt.Printf("Closed issue %s\n", newIssue.ID)
fmt.Println("\n✅ Library usage demo complete!")
}