Skip to content

A Go SDK for interacting with the Anytype API to manage spaces, objects, and perform searches. This library provides a feature-rich, fluent interface to integrate Anytype functionality into your Go applications.

License

Notifications You must be signed in to change notification settings

epheo/anytype-go

Repository files navigation

Anytype-Go SDK

Go Report Card GoDoc License: Apache 2.0

A Go SDK for interacting with the Anytype API to manage spaces, objects, and perform searches. This library provides a feature-rich, fluent interface to integrate Anytype functionality into your Go applications.

Table of Contents

πŸ“‹ Overview

Anytype-Go provides a Go SDK for interacting with Anytype's local API. This SDK offers a clean, fluent interface for:

  • Managing spaces and their members
  • Creating, reading, updating, and deleting objects
  • Searching for objects using various filters
  • Exporting objects to different formats
  • Working with object types, templates, and properties

πŸ“₯ Installation

go get github.com/epheo/anytype-go

Import both the main package and client implementation:

import (
    "github.com/epheo/anytype-go"
    _ "github.com/epheo/anytype-go/client" // Register client implementation
)

🚦 Quick Start

πŸ“ More complete examples can be found in the examples directory, including full implementations of authentication, working with spaces, objects, and more.

Authentication

To use the Anytype API, you need to obtain an AppKey and SessionToken. Here's how to get them:

// Step 1: Initiate authentication and get challenge ID
authResponse, err := client.Auth().DisplayCode(ctx, "MyAnytypeApp")
if err != nil {
    log.Fatalf("Failed to initiate authentication: %v", err)
}
challengeID := authResponse.ChallengeID

// Step 2: User needs to enter the code shown in Anytype app
fmt.Println("Please enter the authentication code shown in Anytype:")
var code string
fmt.Scanln(&code)

// Step 3: Complete authentication and get tokens
tokenResponse, err := client.Auth().GetToken(ctx, challengeID, code)
if err != nil {
    log.Fatalf("Authentication failed: %v", err)
}

// Now you have your authentication tokens
appKey := tokenResponse.AppKey
sessionToken := tokenResponse.SessionToken

// Create authenticated client
client := anytype.NewClient(
    anytype.WithBaseURL("http://localhost:31009"), // Default Anytype local API URL
    anytype.WithAppKey(appKey),
    anytype.WithSessionToken(sessionToken),
)

Note: The authentication flow requires user interaction. When you call DisplayCode, Anytype will show a verification code that must be entered in your application.

Working with Spaces

// List all spaces
spaces, err := client.Spaces().List(ctx)

// Get a specific space
space, err := client.Space(spaceID).Get(ctx)

// Create a new space
newSpace, err := client.Spaces().Create(ctx, anytype.CreateSpaceRequest{
    Name:        "My New Workspace",
    Description: "Created via the Go SDK",
})

Working with Objects

// Get an object
object, err := client.Space(spaceID).Object(objectID).Get(ctx)

// Delete an object
err = client.Space(spaceID).Object(objectID).Delete(ctx)

// Export an object to markdown
exportResult, err := client.Space(spaceID).Object(objectID).Export(ctx, "markdown")

// Create a new object
newObject, err := client.Space(spaceID).Objects().Create(ctx, anytype.CreateObjectRequest{
    TypeKey:     "ot-page",
    Name:        "My New Page",
    Description: "Created via the Go SDK",
    Body:        "# This is a new page\n\nWith some content in markdown format.",
    Icon: &anytype.Icon{
        Type:  "emoji",
        Value: "πŸ“„",
    },
})

Searching

// Search within a specific space
results, err := client.Space(spaceID).Search(ctx, anytype.SearchRequest{
    Query: "important notes",
    Sort: anytype.SortOptions{
        Property:  anytype.SortPropertyLastModifiedDate,
        Direction: anytype.SortDirectionDesc,
    },
    Types: []string{"ot-note", "ot-page"}, // Filter by specific types
})

πŸ”§ Advanced Examples

Working with Object Types and Templates

// List available object types in a space
objectTypes, err := client.Space(spaceID).Types().List(ctx)

// Get details of a specific object type
typeDetails, err := client.Space(spaceID).Type(typeID).Get(ctx)

// Create a new template based on an object type
newTemplate, err := client.Space(spaceID).Templates().Create(ctx, anytype.CreateTemplateRequest{
    Name:        "Project Template",
    Description: "Template for project documentation",
    TypeID:      typeID,
    Icon: &anytype.Icon{
        Type:  "emoji",
        Value: "πŸ“‹",
    },
    DefaultProperties: []string{"name", "description", "status", "deadline"},
})

// Get a specific template
template, err := client.Space(spaceID).Template(templateID).Get(ctx)

Managing Object Properties

// Update object properties
err := client.Space(spaceID).Object(objectID).UpdateProperties(ctx, anytype.UpdatePropertiesRequest{
    Properties: map[string]interface{}{
        "name":        "Updated Title",
        "description": "Updated description",
        "status":      "In Progress",
        "priority":    "High",
        "deadline":    time.Now().AddDate(0, 0, 14).Format(time.RFC3339),
    },
})

// Add a relation to another object
err := client.Space(spaceID).Object(objectID).AddRelation(ctx, relatedObjectID, "related-to")

Working with Lists and Views

// Create a new list to organize objects
newList, err := client.Space(spaceID).Lists().Create(ctx, anytype.CreateListRequest{
    Name:        "Project Tasks",
    Description: "All tasks for our current project",
    Icon: &anytype.Icon{
        Type:  "emoji",
        Value: "πŸ“",
    },
})

// Add objects to a list
err := client.Space(spaceID).List(listID).AddObjects(ctx, []string{objectID1, objectID2})

// Create a custom view for a list
newView, err := client.Space(spaceID).List(listID).Views().Create(ctx, anytype.CreateViewRequest{
    Name: "Priority View",
    Type: "board",
    GroupBy: []string{"priority"},
    SortBy: []anytype.SortOptions{
        {
            Property:  "deadline",
            Direction: anytype.SortDirectionAsc,
        },
    },
    Filters: []anytype.FilterCondition{
        {
            Property: "status",
            Operator: anytype.OperatorNotEquals,
            Value:    "Completed",
        },
    },
})

πŸ’‘ Design Philosophy

The Anytype-Go SDK is built around three core design principles:

1. Fluent Interface Pattern

exportedMarkdown, err := client.
    Space(spaceID).
    Object(objectID).
    Export(ctx, "markdown")

Benefits:

  • Readable code that mirrors natural language
  • IDE autocomplete reveals available operations
  • Compile-time type safety
  • Reduced boilerplate code

2. Domain-Driven Design

The SDK is organized around Anytype's core concepts (spaces, objects, types) with interfaces that map directly to these concepts:

  • SpaceClient and SpaceContext for spaces
  • ObjectClient and ObjectContext for objects
  • TypeClient for object types
  • ListClient for lists and views

3. Naming Convention

The naming of interfaces and types in this library follows a clear and consistent pattern to improve code readability and API fluency:

  • <Entity>Client: Represents a client that operates on collections of entities (e.g., SpaceClient for working with multiple spaces, TypeClient for working with multiple object types). These clients handle operations like listing, searching, and creating new entities.
  • <Entity>Context: Represents a client that operates on a single, specific entity instance (e.g., SpaceContext for a single space, ObjectContext for a single object). These handle operations like getting details, updating, or deleting a specific entity.

This naming convention creates a fluent, chainable API where:

  1. Collection operations use the <Entity>Client pattern (e.g., client.Spaces().List())
  2. Instance operations use the <Entity>Context pattern (e.g., client.Space(spaceID).Get())
  3. Nested resources follow a natural hierarchy (e.g., client.Space(spaceID).Object(objectID).Export())

This design enables intuitive navigation through the API that mirrors natural language and domain concepts.

4. Middleware Architecture

HTTP Request β†’ ValidationMiddleware β†’ RetryMiddleware β†’ DisconnectMiddleware β†’ HTTP Client β†’ API

Each middleware handles a specific concern:

  • Validation: Validates requests before sending
  • Retry: Handles transient errors with configurable policies
  • Disconnect: Manages network interruptions

πŸ“š API Reference

For detailed API documentation, see GoDoc.

βœ… Best Practices

  1. Reuse the client instance across your application
  2. Use context for cancellation to control timeouts
  3. Handle rate limiting with appropriate backoff strategies
  4. Validate inputs before making API calls
  5. Check for errors and handle them appropriately
  6. Use the fluent interface for cleaner, more readable code

πŸ”§ Troubleshooting

  • Authentication Failures**: Verify your app key and session token
  • Connection Issues**: Ensure Anytype is running locally
  • Rate Limiting**: Implement backoff if making many requests

πŸ§ͺ Testing

The SDK testing approach focuses on behavior verification using mock implementations:

Unit Tests with Mocks

tests: Tests ensure that client interfaces behave according to specifications using mock implementations to simulate API responses.

go test -v ./tests/...

API Coverage Tests

tests_api_coverage: Tests verify that all API endpoints are properly defined and can be called with appropriate parameters.

go test -v ./tests_api_coverage/...

The test infrastructure uses mock implementations (in tests/mocks) to simulate the Anytype API, allowing thorough testing without requiring a running Anytype instance.

πŸ‘₯ Contributing

  1. Fork the repository
  2. Create your feature branch
  3. Commit your changes
  4. Push to the branch
  5. Create a new Pull Request

πŸ“œ License

Apache License 2.0 - see LICENSE file for details.

About

A Go SDK for interacting with the Anytype API to manage spaces, objects, and perform searches. This library provides a feature-rich, fluent interface to integrate Anytype functionality into your Go applications.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published