backstage-client 0.1.4

A Rust client library for interacting with the Backstage Catalog API. Provides type-safe access to Backstage entities with async support, filtering, and comprehensive error handling.
Documentation
# Backstage Client Library

The `backstage-client` library is a Rust-based client for interacting with the Backstage API. It allows you to retrieve various entities from the Backstage API catalog, including components, APIs, resources, systems, groups, locations, domains, and templates.

## Features

- **Retrieve Entities**: Fetch different types of entities from the Backstage API catalog.
- **Filter Support**: Use filters to retrieve specific kinds of entities.

## Supported Entity Kinds

The library supports the following entity kinds:

- **Component**: Represents a component in the Backstage catalog.
- **API**: Represents an API in the Backstage catalog.
- **Resource**: Represents a resource in the Backstage catalog.
- **System**: Represents a system in the Backstage catalog.
- **Group**: Represents a group in the Backstage catalog.
- **Location**: Represents a location in the Backstage catalog.
- **Domain**: Represents a domain in the Backstage catalog.
- **Template**: Represents a template in the Backstage catalog.

## Installation

Add the `backstage-client` crate to your `Cargo.toml` file:

```toml
[dependencies]
backstage-client = "0.1.2"  # Replace with the latest version
tokio = { version = "1", features = ["full"] }
log = "0.4"
env_logger = "0.10"
```

## Usage
### Example 1: Fetching all Entities

Here's an example of how to use the backstage-client library to fetch all entities from the Backstage API catalog:

```rs
use backstage_client::{BackstageClient, entities::Entity, ClientError};
use log::{info, error};
use std::env;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize logging
    env_logger::init();

    // Get configuration from environment variables
    let base_url = env::var("BACKSTAGE_URL")
        .unwrap_or_else(|_| "https://backstage.example.com".to_string());
    let token = env::var("BACKSTAGE_TOKEN")
        .expect("BACKSTAGE_TOKEN environment variable must be set");

    // Create a new Backstage client
    let client = BackstageClient::new(&base_url, &token)?;

    // Fetch entities without filters
    match client.fetch_entities::<Entity>(None).await {
        Ok(entities) => {
            info!("Successfully fetched {} entities", entities.len());
            for entity in entities.iter().take(3) {
                info!("Entity: {} ({})", entity.name(), entity.kind());
            }
        }
        Err(e) => {
            error!("Error fetching entities: {}", e);
            return Err(e.into());
        }
    }

    Ok(())
}
```

### Example 2: Fetching Entities with Filters

You can also use filters to retrieve specific kinds of entities. Here's an example of how to fetch `component`s of type `service`:

```rs
use backstage_client::{BackstageClient, entities::Entity, ClientError};
use log::{info, error};
use std::{collections::HashMap, env};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize logging
    env_logger::init();

    // Get configuration from environment variables
    let base_url = env::var("BACKSTAGE_URL")
        .unwrap_or_else(|_| "https://backstage.example.com".to_string());
    let token = env::var("BACKSTAGE_TOKEN")
        .expect("BACKSTAGE_TOKEN environment variable must be set");

    // Create a new Backstage client
    let client = BackstageClient::new(&base_url, &token)?;

    // Define filters to fetch components
    let mut filters = HashMap::new();
    filters.insert("kind".to_string(), "Component".to_string());
    filters.insert("spec.type".to_string(), "service".to_string());

    // Fetch components with filters
    match client.fetch_entities::<Entity>(Some(filters)).await {
        Ok(components) => {
            info!("Successfully fetched {} components", components.len());
            for component in components.iter().take(5) {
                info!("Component: {} - {}", 
                    component.name(), 
                    component.description().unwrap_or("No description")
                );
            }
        }
        Err(e) => {
            error!("Error fetching components: {}", e);
            return Err(e.into());
        }
    }

    Ok(())
}
```

### Example 3: Getting a Specific Entity

You can retrieve a specific entity by its kind, namespace, and name:

```rs
use backstage_client::{BackstageClient, entities::Entity, ClientError};
use log::{info, error};
use std::env;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize logging
    env_logger::init();

    // Get configuration from environment variables
    let base_url = env::var("BACKSTAGE_URL")
        .unwrap_or_else(|_| "https://backstage.example.com".to_string());
    let token = env::var("BACKSTAGE_TOKEN")
        .expect("BACKSTAGE_TOKEN environment variable must be set");

    // Create a new Backstage client
    let client = BackstageClient::new(&base_url, &token)?;

    // Get a specific component by name
    match client.get_entity::<Entity>("Component", Some("default"), "my-service").await {
        Ok(entity) => {
            info!("Found entity: {}", entity);
            info!("  Kind: {}", entity.kind());
            info!("  Name: {}", entity.name());
            info!("  Namespace: {}", entity.namespace());
            if let Some(description) = entity.description() {
                info!("  Description: {}", description);
            }
        }
        Err(e) => {
            error!("Error fetching entity: {}", e);
            return Err(e.into());
        }
    }

    Ok(())
}
```