infrahub 0.2.1

small graphql client for infrahub
Documentation
# case study: procurement contract

this example uses a custom object loaded via `extension_contract.yml`:

```yaml
nodes:
  - name: Contract
    namespace: Procurement
    attributes:
      - name: contract_ref
        kind: Text
      - name: description
        kind: Text
        optional: true
      - name: start_time
        kind: DateTime
      - name: end_time
        kind: DateTime
        optional: true
```

## typed query (concise)

```rust,no_run
use infrahub::{Client, ClientConfig};
use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct Data {
    #[serde(rename = "ProcurementContract")]
    procurement_contract: Contracts,
}

#[derive(Debug, Deserialize)]
struct Contracts {
    edges: Vec<Edge>,
}

#[derive(Debug, Deserialize)]
struct Edge {
    node: Option<ContractNode>,
}

#[derive(Debug, Deserialize)]
struct ContractNode {
    id: String,
    contract_ref: TextAttr,
    description: Option<TextAttr>,
}

#[derive(Debug, Deserialize)]
struct TextAttr {
    value: Option<String>,
}

# async fn example() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new(ClientConfig::new("http://localhost:8000", "token"))?;

let query = r#"
query($ref: String) {
  ProcurementContract(contract_ref__value: $ref) {
    edges {
      node {
        id
        contract_ref { value }
        description { value }
      }
    }
  }
}
"#;

let vars = serde_json::json!({ "ref": "contract-001" });
let response = client.execute::<Data>(query, Some(vars), None).await?;

for edge in response.data.unwrap().procurement_contract.edges {
    if let Some(node) = edge.node {
        println!("{} -> {:?}", node.id, node.contract_ref.value);
    }
}
# Ok(())
# }
```

## generated client (full surface)

if you generate a full client with `infrahub-codegen`, you get a method for the custom object:

```rust,no_run
use infrahub::{Client, ClientConfig};
use infrahub_generated::GeneratedClient;

# async fn example() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new(ClientConfig::new("http://localhost:8000", "token"))?;

let response = client
    .generated()
    .procurement_contract(
        None,        // offset
        Some(20),    // limit
        None,        // order
        None,        // ids
        None, None, None, // display_label filters
        None,        // hfid
        None, None, None, None, None, None, // start_time filters
        None, None, None, None, None, None, // description filters
        None, None, None, None, None, None, // contract_ref filters
        None, None, None, None, None, None, // end_time filters
        None, None, None, None, None, None, // any filters
        None,        // partial_match
        None, None, None, None, None, None, // node metadata filters
        None, None, None, None, None, None, // profiles filters
        None, None, None, None, None, None, // subscriber_of_groups filters
        None, None, None, None, None, None, // organization filters
        None, None, None, None, None, None, // member_of_groups filters
        None,        // request_branch
    )
    .await?;

let data = response.data.unwrap();
println!("count: {}", data.procurement_contract.count);
# Ok(())
# }
```

notes:
- generated methods include every filter arg exposed by the schema.
- for ergonomic usage, prefer the concise typed query form.
 - the generated crate also includes `api()` helpers for shorter accessors.