args-api 0.1.0

Shared API contract types and endpoint definitions for args.
Documentation
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use uuid::Uuid;

use crate::ApiResource;

/// Shared response envelope for paginated list endpoints.
///
/// `next_cursor` is `None` (omitted from the JSON via `skip_serializing_if`)
/// on the final page. Clients pass it back as `?cursor=...` to fetch the
/// next page; the encoding is opaque.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Page<T> {
    pub data: Vec<T>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub next_cursor: Option<String>,
}

impl<T: ApiResource + DeserializeOwned> ApiResource for Page<T> {}

/// Shared author projection returned across domains (bug, question, …).
#[derive(ApiResource, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuthorResource {
    pub id: Uuid,
    pub name: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub image_updated_at: Option<DateTime<Utc>>,
}

/// The capacity in which a user relates to a repository.
#[derive(ApiResource, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RepositoryRole {
    Maintainer,
    User,
}

/// The capacity in which a user relates to an organization. `User` is the
/// fallback for a viewer who is not a member (or is unauthenticated); members
/// are only ever `Admin` or `Member`.
#[derive(ApiResource, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum OrganizationRole {
    Admin,
    Member,
    User,
}