kanboard-api/README.md

240 lines
5.4 KiB
Markdown
Raw Permalink Normal View History

# kanboard-api
Go library for the [Kanboard](https://kanboard.org/) JSON-RPC API. Provides a fluent, chainable API for integrating Kanboard into Go applications.
## Installation
```bash
go get code.beautifulmachines.dev/jakoubek/kanboard-api
```
## Quick Start
```go
package main
import (
"context"
"fmt"
"log"
"time"
kanboard "code.beautifulmachines.dev/jakoubek/kanboard-api"
)
func main() {
ctx := context.Background()
// Create client with API token
client := kanboard.NewClient("https://kanboard.example.com").
WithAPIToken("your-api-token").
WithTimeout(30 * time.Second)
// Create a task using the fluent API
task, err := client.Board(1).CreateTaskFromParams(ctx,
kanboard.NewTask("My Task").
WithDescription("Task description").
WithPriority(2).
WithTags("urgent", "backend"))
if err != nil {
log.Fatal(err)
}
fmt.Printf("Created task: %d\n", task.ID)
}
```
## Authentication
The library supports two authentication methods:
### API Token (Recommended)
```go
client := kanboard.NewClient("https://kanboard.example.com").
WithAPIToken("your-api-token")
```
### Username/Password
```go
client := kanboard.NewClient("https://kanboard.example.com").
WithBasicAuth("admin", "password")
```
## API Usage
### Fluent API
The fluent API provides chainable, scoped operations:
```go
// Board-scoped operations
board := client.Board(projectID)
tasks, _ := board.GetTasks(ctx, kanboard.StatusActive)
columns, _ := board.GetColumns(ctx)
categories, _ := board.GetCategories(ctx)
// Task-scoped operations
task := client.Task(taskID)
task.Close(ctx)
task.MoveToNextColumn(ctx)
task.AddTag(ctx, "reviewed")
task.AddComment(ctx, userID, "Comment text")
```
### Direct API
For lower-level access, use the direct API methods:
```go
// Projects
projects, _ := client.GetAllProjects(ctx)
project, _ := client.GetProjectByID(ctx, projectID)
project, _ := client.GetProjectByName(ctx, "My Project")
// Tasks
tasks, _ := client.GetAllTasks(ctx, projectID, kanboard.StatusActive)
task, _ := client.GetTask(ctx, taskID)
task, _ := client.CreateTask(ctx, kanboard.CreateTaskRequest{
Title: "New Task",
ProjectID: projectID,
})
// Global search across all projects
results, _ := client.SearchTasksGlobal(ctx, "search query")
```
### Task Creation
Use `TaskParams` for fluent task creation:
```go
params := kanboard.NewTask("Task Title").
WithDescription("Detailed description").
WithCategory(categoryID).
WithOwner(userID).
WithColor("red").
WithPriority(3).
WithScore(5).
WithDueDate(time.Now().Add(7 * 24 * time.Hour)).
WithTags("feature", "v2.0").
InColumn(columnID).
InSwimlane(swimlaneID)
task, err := client.Board(projectID).CreateTaskFromParams(ctx, params)
```
### Task Updates
Use `TaskUpdateParams` for partial updates:
```go
updates := kanboard.NewTaskUpdate().
SetTitle("Updated Title").
SetDescription("New description").
SetPriority(1)
err := client.Task(taskID).Update(ctx, updates)
```
### Task Movement
```go
// Move to next/previous column in workflow
client.Task(taskID).MoveToNextColumn(ctx)
client.Task(taskID).MoveToPreviousColumn(ctx)
// Move to specific column
client.Task(taskID).MoveToColumn(ctx, columnID)
// Move to different project
client.Task(taskID).MoveToProject(ctx, newProjectID)
```
### Comments
```go
// Get all comments
comments, _ := client.Task(taskID).GetComments(ctx)
// Add a comment
comment, _ := client.Task(taskID).AddComment(ctx, userID, "Comment text")
```
### Links
```go
// Get task links
links, _ := client.Task(taskID).GetLinks(ctx)
// Link tasks together
client.Task(taskID).LinkTo(ctx, otherTaskID, linkID)
```
### Files
```go
// Get attached files
files, _ := client.Task(taskID).GetFiles(ctx)
// Upload a file
content := []byte("file content")
fileID, _ := client.Task(taskID).UploadFile(ctx, "document.txt", content)
```
## Error Handling
The library provides typed errors for common scenarios:
```go
task, err := client.GetTask(ctx, taskID)
if err != nil {
if kanboard.IsNotFound(err) {
// Handle not found
}
if kanboard.IsUnauthorized(err) {
// Handle auth failure
}
if kanboard.IsAPIError(err) {
// Handle Kanboard API error
}
}
```
Available sentinel errors:
- `ErrNotFound`, `ErrProjectNotFound`, `ErrTaskNotFound`, `ErrColumnNotFound`
- `ErrUnauthorized`, `ErrForbidden`
- `ErrConnectionFailed`, `ErrTimeout`
- `ErrAlreadyInLastColumn`, `ErrAlreadyInFirstColumn`
- `ErrEmptyTitle`, `ErrInvalidProjectID`
## Thread Safety
The client is safe for concurrent use by multiple goroutines. Request IDs are generated atomically.
## Tag Operations Warning
Kanboard's `setTaskTags` API **replaces all tags**. The library implements read-modify-write internally for `AddTag` and `RemoveTag` operations. This is not atomic - concurrent tag modifications may cause data loss.
```go
// Safe: single operation
task.SetTags(ctx, "tag1", "tag2", "tag3")
// Caution: concurrent calls to AddTag/RemoveTag may conflict
task.AddTag(ctx, "new-tag")
task.RemoveTag(ctx, "old-tag")
```
## Client Configuration
```go
client := kanboard.NewClient("https://kanboard.example.com").
WithAPIToken("token").
WithTimeout(60 * time.Second).
WithHTTPClient(customHTTPClient).
WithLogger(slog.Default())
```
## License
MIT License - see [LICENSE](LICENSE) for details.