Skip to main content

Go SDK

Complete guide to using Cocobase with Go applications.

Installation

go get github.com/lordace-coder/cocobase-go

Quick Start

Initialize Cocobase

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/lordace-coder/cocobase-go/cocobase"
)

func main() {
    client := cocobase.NewClient(cocobase.Config{
        APIKey:  "YOUR_API_KEY",
        BaseURL: "https://api.cocobase.buzz", // Optional
    })

    ctx := context.Background()
    _ = ctx // use ctx in your operations
}
// With custom storage (for token persistence)
import "github.com/lordace-coder/cocobase-go/storage"

store := storage.NewMemoryStorage()
// Or file-based:
// store, _ := storage.NewFileStorage(".cocobase/storage.json")

client := cocobase.NewClient(cocobase.Config{
    APIKey:  "YOUR_API_KEY",
    Storage: store,
})

Basic Operations

// List documents (no filters)
docs, err := client.ListDocuments(ctx, "posts", nil)

// List with query
query := cocobase.NewQuery().Where("status", "active").Limit(20)
docs, err := client.ListDocuments(ctx, "posts", query)

// Get single document
doc, err := client.GetDocument(ctx, "posts", "doc-id")

// Create document
created, err := client.CreateDocument(ctx, "posts", map[string]interface{}{
    "title":   "My First Post",
    "content": "Hello World!",
})

// Update document
updated, err := client.UpdateDocument(ctx, "posts", "doc-id", map[string]interface{}{
    "title": "Updated Title",
})

// Delete document
err = client.DeleteDocument(ctx, "posts", "doc-id")

Querying Data

Simple Filters

query := cocobase.NewQuery().Where("status", "active")
docs, err := client.ListDocuments(ctx, "users", query)

Comparison Operators

query := cocobase.NewQuery().
    Filter("age", "gte", 18).
    Filter("age", "lte", 65)

String Operations

query := cocobase.NewQuery().
    Filter("email", "endswith", "gmail.com")

IN Operator

query := cocobase.NewQuery().
    Filter("role", "in", "admin,moderator,support")

NULL Checks

query := cocobase.NewQuery().
    Filter("deletedAt", "isnull", true)

Simple OR

query := cocobase.NewQuery().
    Where("status", "active").
    Or("isPremium", "eq", true).
    Or("isVerified", "eq", true)

Named OR Groups

query := cocobase.NewQuery().
    OrGroup("tier", "isPremium", "eq", true).
    OrGroup("tier", "isVerified", "eq", true).
    OrGroup("location", "country", "eq", "US").
    OrGroup("location", "country", "eq", "UK")
query := cocobase.NewQuery().
    MultiFieldOr([]string{"name", "email"}, "contains", "john")

Sorting and Pagination

query := cocobase.NewQuery().
    Where("status", "active").
    Sort("createdAt").
    OrderDesc().
    Limit(50).
    Offset(100)

docs, err := client.ListDocuments(ctx, "users", query)

Working with Structs

Define Your Types

type Book struct {
    Title       string  `json:"title"`
    Author      string  `json:"author"`
    Price       float64 `json:"price"`
    PublishedAt string  `json:"publishedAt,omitempty"`
}

Create with Structs

newBook := Book{
    Title:  "Clean Code",
    Author: "Robert Martin",
    Price:  45.99,
}

created, err := client.CreateDocument(ctx, "books", newBook)

Parse Response to Struct

doc, err := client.GetDocument(ctx, "books", "doc-id")
if err != nil {
    log.Fatal(err)
}

var book Book
err = doc.DataAs(&book)
if err != nil {
    log.Fatal(err)
}

fmt.Println(book.Title)

Authentication

Initialize Auth (restore session from storage)

err := client.InitAuth(ctx)

Register

err := client.Register(ctx, "user@example.com", "password123", map[string]interface{}{
    "firstName": "John",
    "lastName":  "Doe",
})
// Pass nil for no extra data:
// err := client.Register(ctx, "user@example.com", "password123", nil)

Login

err = client.Login(ctx, "user@example.com", "password123")

Get Current User

user, err := client.GetCurrentUser(ctx)
fmt.Println("User ID:", user.ID)
fmt.Println("Email:", user.Email)

Update User

newEmail := "new@example.com"
user, err = client.UpdateUser(ctx, map[string]interface{}{
    "phone": "+1234567890",
}, &newEmail, nil)

Logout

err = client.Logout()

Check Authentication

if client.IsAuthenticated() {
    fmt.Println("User is logged in")
}

Check Role

if client.HasRole("admin") {
    fmt.Println("User is an admin")
}

Real-time Data

Watch a Collection

conn, err := client.WatchCollection(ctx, "posts", func(event cocobase.Event) {
    fmt.Printf("Event: %s\n", event.Event)
    fmt.Printf("Data: %+v\n", event.Data)
}, "posts-watcher") // last param is connection name (optional label)

if err != nil {
    log.Fatal(err)
}

// Close when done
defer conn.Close()

Error Handling

doc, err := client.GetDocument(ctx, "posts", "non-existent-id")
if err != nil {
    var apiErr *cocobase.APIError
    if errors.As(err, &apiErr) {
        fmt.Println("Status:", apiErr.StatusCode)
        fmt.Println("Error:", apiErr.Body)
    } else {
        fmt.Println("Error:", err)
    }
}

Context Support

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

doc, err := client.GetDocument(ctx, "posts", "doc-id")
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        fmt.Println("Request timed out")
    }
}

Best Practices

1. Use Structs for Type Safety

// Good
type Post struct {
    Title   string `json:"title"`
    Content string `json:"content"`
}

var post Post
doc.DataAs(&post)

// Avoid
data := doc.Data.(map[string]interface{})

2. Always Handle Errors

doc, err := client.GetDocument(ctx, "posts", id)
if err != nil {
    return nil, fmt.Errorf("failed to get post: %w", err)
}

3. Use Environment Variables

client := cocobase.NewClient(cocobase.Config{
    APIKey: os.Getenv("COCOBASE_API_KEY"),
})

4. Always Set Limits

// Good
query := cocobase.NewQuery().Limit(20)
docs, err := client.ListDocuments(ctx, "posts", query)

// Bad - could return thousands
docs, err := client.ListDocuments(ctx, "posts", nil)

Next Steps