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
use super::{
    api::ApiEntity, component::Component, domain::DomainEntity, group::GroupEntity,
    location::LocationEntity, resource::ResourceEntity, system::SystemEntity,
    template::TemplateEntity, user::UserEntity,
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Debug, Serialize, Deserialize)]
pub struct Metadata {
    pub name: String,
    pub description: Option<String>,
    pub annotations: Option<HashMap<String, String>>, // Use HashMap for annotations
    pub tags: Option<Vec<String>>,
    pub namespace: Option<String>, // Use Option if namespace can be missing
    pub uid: Option<String>,       // Use Option if uid can be missing
    pub etag: Option<String>,      // Use Option if etag can be missing
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Relation {
    pub r#type: String,
    pub target_ref: Option<String>,
    pub target: Target,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Target {
    pub kind: String,
    pub namespace: String,
    pub name: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "PascalCase")]
pub enum Entity {
    Component(Component),
    API(ApiEntity),
    Resource(ResourceEntity),
    System(SystemEntity),
    Group(GroupEntity),
    Location(LocationEntity),
    Domain(DomainEntity),
    Template(TemplateEntity),
    User(UserEntity),
}

impl Entity {
    /// Returns the kind of the entity as a string.
    pub fn kind(&self) -> &'static str {
        match self {
            Entity::Component(_) => "Component",
            Entity::API(_) => "API",
            Entity::Resource(_) => "Resource",
            Entity::System(_) => "System",
            Entity::Group(_) => "Group",
            Entity::Location(_) => "Location",
            Entity::Domain(_) => "Domain",
            Entity::Template(_) => "Template",
            Entity::User(_) => "User",
        }
    }

    /// Returns the metadata of the entity.
    pub fn metadata(&self) -> &Metadata {
        match self {
            Entity::Component(c) => &c.metadata,
            Entity::API(a) => &a.metadata,
            Entity::Resource(r) => &r.metadata,
            Entity::System(s) => &s.metadata,
            Entity::Group(g) => &g.metadata,
            Entity::Location(l) => &l.metadata,
            Entity::Domain(d) => &d.metadata,
            Entity::Template(t) => &t.metadata,
            Entity::User(u) => &u.metadata,
        }
    }

    /// Returns the relations of the entity if available.
    pub fn relations(&self) -> Option<&Vec<Relation>> {
        match self {
            Entity::Component(c) => c.relations.as_ref(),
            Entity::API(a) => Some(&a.relations),
            Entity::Resource(r) => Some(&r.relations),
            Entity::System(s) => Some(&s.relations),
            Entity::Group(g) => Some(&g.relations),
            Entity::Location(l) => l.relations.as_ref(),
            Entity::Domain(d) => Some(&d.relations),
            Entity::Template(t) => t.relations.as_ref(),
            Entity::User(u) => u.relations.as_ref(),
        }
    }

    /// Returns the name of the entity from its metadata.
    pub fn name(&self) -> &str {
        &self.metadata().name
    }

    /// Returns the namespace of the entity, defaulting to "default" if not specified.
    pub fn namespace(&self) -> &str {
        self.metadata().namespace.as_deref().unwrap_or("default")
    }

    /// Returns the fully qualified entity reference in the format "kind:namespace/name".
    pub fn entity_ref(&self) -> String {
        format!(
            "{}:{}/{}",
            self.kind().to_lowercase(),
            self.namespace(),
            self.name()
        )
    }

    /// Returns the description of the entity if available.
    pub fn description(&self) -> Option<&str> {
        self.metadata().description.as_deref()
    }

    /// Returns the tags associated with the entity.
    pub fn tags(&self) -> Option<&Vec<String>> {
        self.metadata().tags.as_ref()
    }

    /// Returns the annotations associated with the entity.
    pub fn annotations(&self) -> Option<&HashMap<String, String>> {
        self.metadata().annotations.as_ref()
    }

    /// Checks if the entity has a specific tag.
    pub fn has_tag(&self, tag: &str) -> bool {
        self.tags()
            .map(|tags| tags.contains(&tag.to_string()))
            .unwrap_or(false)
    }

    /// Gets an annotation value by key.
    pub fn get_annotation(&self, key: &str) -> Option<&str> {
        self.annotations()
            .and_then(|annotations| annotations.get(key))
            .map(|s| s.as_str())
    }
}

impl std::fmt::Display for Entity {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{} ({})", self.entity_ref(), self.kind())
    }
}