Go SDK for Hyperfluid data access with two fluent APIs:
- Progressive API (Type-safe, resource management) - NEW! β¨
- Catalog-First API (Simple queries)
# Install
go get github.com/nudibranches-tech/bifrost-hyperfluid-sdk-dev/sdkNavigate the resource hierarchy with type safety and contextual operations:
// Full path: Org β Harbor β DataDock β Catalog β Schema β Table
resp, err := client.
Org(orgID). // OrgBuilder - can ListHarbors(), CreateHarbor()
Harbor(harborID). // HarborBuilder - can ListDataDocks()
DataDock(dataDockID). // DataDockBuilder - can WakeUp(), Sleep(), RefreshCatalog()
Catalog(catalogName). // CatalogBuilder - can ListSchemas()
Schema(schemaName). // SchemaBuilder - can ListTables()
Table(tableName). // TableQueryBuilder - can query
Limit(10).
Get(ctx)Benefits:
- β Type-safe: Each level is a different type
- β IDE autocomplete shows only valid methods
- β Resource management (WakeUp, Sleep, RefreshCatalog)
- β Listing at each level (ListHarbors, ListSchemas, etc.)
See: PROGRESSIVE_API.md for complete documentation
Jump directly to tables when you just need data:
import (
"context"
"fmt"
"github.com/nudibranches-tech/bifrost-hyperfluid-sdk-dev/sdk"
"github.com/nudibranches-tech/bifrost-hyperfluid-sdk-dev/sdk/utils"
)
func main() {
// Configure the client
config := utils.Configuration{
BaseURL: "https://bifrost.hyperfluid.cloud",
OrgID: "your-org-id",
Token: "your-token",
// or use Keycloak for token management
}
// Create a new client
client := sdk.NewClient(config)
// Simple query with fluent API
resp, err := client.
Catalog("sales").
Schema("public").
Table("orders").
Limit(10).
Get(context.Background())
if err != nil {
// Handle error
}
fmt.Println(resp.Data)
}Benefits:
- β Simple and concise
- β Perfect for data queries
- β No need for intermediate IDs
// List resources at each level
harbors, err := client.Org(orgID).ListHarbors(ctx)
datadocks, err := client.Org(orgID).Harbor(harborID).ListDataDocks(ctx)
schemas, err := datadock.Catalog("postgres").ListSchemas(ctx)
tables, err := schema.ListTables(ctx)
// Create resources
client.Org(orgID).CreateHarbor(ctx, "my-harbor")
harbor.CreateDataDock(ctx, datadockConfig)
// DataDock lifecycle
datadock := client.Org(orgID).Harbor(harborID).DataDock(dataDockID)
datadock.RefreshCatalog(ctx) // Update metadata
datadock.WakeUp(ctx) // Bring online
datadock.Sleep(ctx) // Save costs
datadock.Update(ctx, config) // Update config// Simple query
resp, err := client.
Org(orgID).
Harbor(harborID).
DataDock(dataDockID).
Catalog("postgres").
Schema("public").
Table("users").
Limit(10).
Get(ctx)
// Complex query with filters
resp, err := client.
Org(orgID).
Harbor(harborID).
DataDock(dataDockID).
Catalog("sales").
Schema("public").
Table("orders").
Select("id", "customer", "total").
Where("status", "=", "completed").
Where("total", ">", 1000).
OrderBy("created_at", "DESC").
Limit(100).
Get(ctx)// Complex query with all features
resp, err := client.
Catalog("sales").
Schema("public").
Table("orders").
Select("id", "customer_name", "total_amount").
Where("status", "=", "completed").
Where("total_amount", ">", 1000).
OrderBy("created_at", "DESC").
Limit(100).
Offset(0).
Get(ctx)
// Override organization ID for specific query
resp, err := client.
Org("different-org-id").
Catalog("catalog").
Schema("schema").
Table("table").
Get(ctx)
// Use raw parameters for advanced cases
resp, err := client.
Catalog("catalog").
Schema("schema").
Table("table").
RawParams(url.Values{"custom_param": {"value"}}).
Get(ctx)
// Building queries step by step
query := client.
Catalog("sales").
Schema("public").
Table("orders")
// Add filters dynamically
if status != "" {
query = query.Where("status", "=", status)
}
// Add pagination
query = query.Limit(pageSize).Offset(page * pageSize)
// Execute
resp, err := query.Get(ctx)HYPERFLUID_ORG_ID- Your organization IDHYPERFLUID_TOKEN- API token (or use Keycloak)
HYPERFLUID_BASE_URL- API endpoint (default:https://bifrost.hyperfluid.cloud)
KEYCLOAK_BASE_URL- Keycloak serverKEYCLOAK_REALM- Realm nameKEYCLOAK_CLIENT_ID- Client ID (required for both grant types)KEYCLOAK_CLIENT_SECRET- Client Secret (for Client Credentials Grant - preferred for services)KEYCLOAK_USERNAME- Your username (for Password Grant - fallback if Client Secret not provided)KEYCLOAK_PASSWORD- Your password (for Password Grant - fallback if Client Secret not provided)
Note: If KEYCLOAK_CLIENT_SECRET is provided, the SDK will prioritize the more secure Client Credentials Grant. Otherwise, it will fall back to the Password Grant if KEYCLOAK_USERNAME and KEYCLOAK_PASSWORD are configured.
sdk/
client.go # Client object and entry points
query_builder.go # Fluent API implementation
request.go # HTTP request handling
auth.go # Authentication (Keycloak support)
utils/ # Utility functions and types
Catalog(name string)- Set the catalog nameSchema(name string)- Set the schema nameTable(name string)- Set the table nameOrg(orgID string)- Override the organization ID from config
Select(columns ...string)- Specify columns to retrieveWhere(column, operator, value)- Add filter conditions- Supported operators:
=,>,<,>=,<=,!=,LIKE,IN
- Supported operators:
OrderBy(column, direction)- Add ordering (ASC/DESC)Limit(n int)- Set maximum rows to returnOffset(n int)- Set number of rows to skipRawParams(url.Values)- Add custom query parameters
Get(ctx)- Execute SELECT query and return resultsCount(ctx)- Get count of matching rowsPost(ctx, data)- Insert new dataPut(ctx, data)- Update existing dataDelete(ctx)- Delete matching rows
resp, err := client.
Catalog("catalog").
Schema("schema").
Table("table").
Get(ctx)
if err != nil {
// Check for specific error types
if errors.Is(err, utils.ErrNotFound) {
log.Println("Resource not found")
} else if errors.Is(err, utils.ErrPermissionDenied) {
log.Println("Permission denied")
} else if errors.Is(err, utils.ErrAuthenticationFailed) {
log.Println("Authentication failed")
} else {
log.Fatalf("Request failed: %v", err)
}
}
if resp.Status != utils.StatusOK {
log.Printf("API error: %s", resp.Error)
}Private SDK for internal use.