use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiSpec {
pub name: String,
pub display_name: String,
pub version: String,
pub description: Option<String>,
pub kind: ApiKind,
pub base_url: Option<String>,
pub types: Vec<TypeDef>,
pub operations: Vec<Operation>,
#[serde(default)]
pub raw_spec: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ApiKind {
OpenApi,
GraphQl,
Grpc,
}
impl ApiKind {
pub fn slug(self) -> &'static str {
match self {
ApiKind::OpenApi => "openapi",
ApiKind::GraphQl => "graphql",
ApiKind::Grpc => "grpc",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum TypeDef {
Struct {
name: String,
description: Option<String>,
fields: Vec<Field>,
},
Enum {
name: String,
description: Option<String>,
variants: Vec<EnumVariant>,
},
Alias {
name: String,
target: String,
},
}
impl TypeDef {
pub fn name(&self) -> &str {
match self {
TypeDef::Struct { name, .. }
| TypeDef::Enum { name, .. }
| TypeDef::Alias { name, .. } => name,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnumVariant {
pub name: String,
pub serde_rename: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Field {
pub name: String,
pub serde_rename: Option<String>,
pub rust_type: String,
pub optional: bool,
pub description: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Operation {
pub id: String,
pub original_id: String,
pub description: Option<String>,
pub protocol: Protocol,
pub endpoint: String,
pub http_method: HttpMethod,
pub params: Vec<Param>,
pub return_type: String,
#[serde(default)]
pub streaming: StreamingMode,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum StreamingMode {
#[default]
Unary,
ServerStream,
ClientStream,
BidiStream,
}
impl StreamingMode {
pub fn is_streaming(self) -> bool {
!matches!(self, StreamingMode::Unary)
}
pub fn label(self) -> &'static str {
match self {
StreamingMode::Unary => "unary",
StreamingMode::ServerStream => "server-stream",
StreamingMode::ClientStream => "client-stream",
StreamingMode::BidiStream => "bidi-stream",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Protocol {
Rest,
GraphQl,
Grpc,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum HttpMethod {
Get,
Post,
Put,
Patch,
Delete,
Options,
Head,
None,
}
impl HttpMethod {
pub fn reqwest_fn(self) -> Option<&'static str> {
Some(match self {
HttpMethod::Get => "get",
HttpMethod::Post => "post",
HttpMethod::Put => "put",
HttpMethod::Patch => "patch",
HttpMethod::Delete => "delete",
HttpMethod::Options => return None,
HttpMethod::Head => "head",
HttpMethod::None => return None,
})
}
pub fn as_str(self) -> &'static str {
match self {
HttpMethod::Get => "GET",
HttpMethod::Post => "POST",
HttpMethod::Put => "PUT",
HttpMethod::Patch => "PATCH",
HttpMethod::Delete => "DELETE",
HttpMethod::Options => "OPTIONS",
HttpMethod::Head => "HEAD",
HttpMethod::None => "NONE",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Param {
pub name: String,
pub original_name: String,
pub rust_type: String,
pub location: ParamLocation,
pub required: bool,
pub description: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ParamLocation {
Path,
Query,
Body,
Header,
GrpcField,
GraphQlVariable,
}