# Go SDK

> Type-safe Go client for Aerostack -- database, auth, cache, storage, AI, realtime, and queue.

The Go SDK provides a type-safe client for all Aerostack services. Designed for Go backends, microservices, CLI tools, and Cloudflare Workers written in Go (via TinyGo).

  **Beta** -- The Go SDK is in active beta. APIs may change between minor versions.

## What you can build

- **API backends** -- REST or gRPC services with built-in auth, database, and caching
- **Microservices** -- Connect existing Go services to Aerostack infrastructure
- **CLI tools** -- Admin scripts for data migration, reporting, and maintenance
- **Background workers** -- Process queue jobs, sync data, or run scheduled tasks
- **Webhooks** -- Receive and process events from external services

## Install

```bash
go get github.com/aerostack/aerostack-go
```

## Initialize

```go

client, err := aerostack.NewClient(aerostack.Config{
    ProjectID: os.Getenv("PROJECT_ID"),
    APIKey:    os.Getenv("API_KEY"),
    BaseURL:   "https://api.aerostack.dev/v1",
})
if err != nil {
    log.Fatal(err)
}
```

## Database

Full SQL access with generics for type-safe query results:

```go
type User struct {
    ID        string `json:"id"`
    Email     string `json:"email"`
    Name      string `json:"name"`
    CreatedAt int64  `json:"created_at"`
}

// Query multiple rows
users, err := client.DB.Query[User](ctx, "SELECT * FROM users WHERE active = 1")

// Query single row (returns nil if not found)
user, err := client.DB.QueryOne[User](ctx, "SELECT * FROM users WHERE id = ?", userID)

// Execute (INSERT, UPDATE, DELETE)
err = client.DB.Exec(ctx, "UPDATE users SET name = ? WHERE id = ?", newName, userID)

// Batch (atomic transaction)
results, err := client.DB.Batch(ctx, []aerostack.BatchStatement{
    {SQL: "INSERT INTO orders (id, user_id, total) VALUES (?, ?, ?)", Params: []any{orderID, userID, total}},
    {SQL: "UPDATE inventory SET stock = stock - ? WHERE product_id = ?", Params: []any{qty, productID}},
})
```

## Auth

Verify JWT tokens from incoming requests:

```go
user, err := client.Auth.VerifyToken(ctx, tokenString)
if err != nil || user == nil {
    http.Error(w, "Unauthorized", 401)
    return
}
fmt.Printf("Authenticated: %s (%s)\n", user.Name, user.Email)
```

## Cache

Key-value cache with TTL support:

```go
// Set with TTL (seconds)
err = client.Cache.Set(ctx, "user:"+userID, userData, 300)

// Get with type-safe deserialization
var cached User
found, err := client.Cache.Get(ctx, "user:"+userID, &cached)
if !found {
    // Cache miss
}

// Check existence
exists, err := client.Cache.Has(ctx, "user:"+userID)

// Delete
err = client.Cache.Delete(ctx, "user:"+userID)
```

## Storage

Upload and manage files:

```go
result, err := client.Storage.Upload(ctx, aerostack.UploadInput{
    File:        reader,
    Path:        "avatars/user-123.jpg",
    ContentType: "image/jpeg",
})
fmt.Println(result.URL) // CDN URL

err = client.Storage.Delete(ctx, "avatars/user-123.jpg")
```

## AI

LLM completions and embeddings:

```go
result, err := client.AI.Complete(ctx, aerostack.CompletionInput{
    Prompt:    "Explain WebSocket pub/sub in two sentences.",
    Model:     "gpt-4o-mini",
    MaxTokens: 256,
})
fmt.Println(result.Text)

// Embeddings
vector, err := client.AI.Embed(ctx, "text to embed")
```

## Queue

Background job processing:

```go
err = client.Queue.Send(ctx, "send-welcome-email", map[string]any{
    "userId": userID,
    "email":  email,
}, aerostack.QueueOptions{
    DelaySeconds: 0,
    MaxRetries:   3,
})
```

## Realtime

Subscribe to channels and broadcast events:

```go
// Subscribe to DB table changes
channel, err := client.Realtime.Channel("orders")
channel.On("INSERT", func(payload aerostack.RealtimePayload) {
    fmt.Printf("New order: %v\n", payload.Data)
})
channel.Subscribe()

// Presence tracking
channel.Track(map[string]any{"userId": "123", "status": "online"})

// Server-side broadcast
client.Socket.Emit(ctx, "order:updated", orderData, "orders/"+orderID)

// Cleanup
channel.Unsubscribe()
```

## Secrets

Retrieve secrets stored in your project:

```go
apiKey, err := client.Secrets.Get(ctx, "STRIPE_SECRET_KEY")
```

## Complete example: HTTP API

```go title="main.go"
package main

    "encoding/json"
    "log"
    "net/http"
    "os"

    "github.com/aerostack/aerostack-go"
)

func main() {
    client, err := aerostack.NewClient(aerostack.Config{
        ProjectID: os.Getenv("PROJECT_ID"),
        APIKey:    os.Getenv("API_KEY"),
    })
    if err != nil {
        log.Fatal(err)
    }

    http.HandleFunc("GET /api/users", func(w http.ResponseWriter, r *http.Request) {
        // Verify auth
        token := r.Header.Get("Authorization")
        user, err := client.Auth.VerifyToken(r.Context(), token)
        if err != nil || user == nil {
            http.Error(w, "Unauthorized", 401)
            return
        }

        // Query database
        users, err := client.DB.Query[User](r.Context(),
            "SELECT id, name, email FROM users ORDER BY created_at DESC LIMIT 50")
        if err != nil {
            http.Error(w, err.Error(), 500)
            return
        }

        json.NewEncoder(w).Encode(users)
    })

    log.Println("Listening on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}
```

## Next steps

- [API Reference](/sdk/go/api-reference) -- Full method listing for all modules
- [Database](/sdk/database) -- Detailed patterns for queries and transactions
- [Realtime](/sdk/realtime) -- Full guide for pub/sub, presence, and DB change events
- [Error Handling](/sdk/error-handling) -- Error types and retry strategies
