4 releases

0.1.3 Oct 4, 2020
0.1.2 Oct 3, 2020
0.1.1 Oct 3, 2020
0.1.0 Oct 3, 2020

#768 in #sdk

MIT license

10KB
94 lines

asana-sdk

A Rust Asana SDK, for the Asana Rest API

This crate uses a model! macro to define flexible Model Structs with a very lean syntax.
These generated structs are used to deserialize entities, select include fields and embed relationships from the Asana API.

See https://docs.rs/asana-sdk for complete documentation.

model!(User "users" {
    email: String,
    name: String,
});

// Simple calls to get one or multiple users
let mut user:  User      = asana.get::<User>("me").await;
let mut users: Vec<User> = asana.list::<User>().await;
model!(TaskWithProjects "tasks" {
    name: String,
    projects: Vec<Project>
} Project);

let mut tasks_with_projects = asana
     .from::<Section>("12345678")
     .list::<TaskWithProjects>().await;

lib.rs:

A Rust Asana SDK, for the Asana Rest API

This crate uses a model! macro to define flexible Model Structs with a very lean syntax. These generated structs are used to deserialize entities, select include fields and embed relationships from the Asana API.

The Asana API returns flexible objects with varying field & relation includes, so this crate uses models provided by the user. This makes the crate also compatible with entities added to the API by Asana in the future.

To make the interface as ergonomic as possible, it relies on two components:

  • A model!() macro to easily define deserialization Structs (serde), together with endpoint urls and field/relation inclusion querystrings.
  • Turbofish operators (get::<Type>()) to make API calls for defined models.

Sample usage

use reqwest::{Error};
use asana_sdk::*;
use asana_sdk::models::Model;

#[tokio::main]
async fn main() -> Result<(), Error> {

    // Connect with your Asana PAT (token), from https://app.asana.com/0/developer-console
    let mut asana = Asana::connect(String::from("1/your:personal-access-token"));

    // A Model Struct linked to the "users" endpoint
    model!(User "users" {
        email: String,
        name: String,
    });

    // Simple calls to get one or multiple users
    let mut user:  User      = asana.get::<User>("me").await;
    let mut users: Vec<User> = asana.list::<User>().await;

    Ok(())
}

A few more advanced examples:

Compound call to list all sections within a specific project

model!(Section "sections" { name: String });
model!(Project "projects" { name: String });

let mut sections = asana
    .from::<Project>("12345678")
    .list::<Section>().await;

A Struct for Tasks including Projects. TaskWithProjects is just an example name, you can give the Struct any name you want.

The call will list all tasks from a specific section, and include all other projects the task is part of.

model!(TaskWithProjects "tasks" {
    name: String,
    projects: Vec<Project>
} Project);

let mut tasks_with_projects = asana
     .from::<Section>("12345678")
     .list::<TaskWithProjects>().await;

Note that all model Structs by default include gid & resource_type, So it's not mandatory to include other fields.

Fields which might be null in the API should be deserialized into an Option

model!(Assignee "assignee" {});
model!(TaskWithAssignee "tasks" {
    name: String,
    assignee: Option<Assignee>
} Assignee);

Dependencies

~4–8.5MB
~163K SLoC