1
0
Fork 0

add openapi parsing

This commit is contained in:
Cyborus 2024-01-10 22:09:06 -05:00
parent cf70a331d7
commit b9ba6e60d1
No known key found for this signature in database
6 changed files with 24721 additions and 22 deletions

12
generator/Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "generator"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
eyre = "0.6.11"
serde = { version = "1.0.195", features = ["derive"] }
serde_json = "1.0.111"
url = { version = "2.5.0", features = ["serde"] }

17
generator/src/main.rs Normal file
View file

@ -0,0 +1,17 @@
use std::ffi::OsString;
mod openapi;
fn main() -> eyre::Result<()> {
let spec = get_spec()?;
dbg!(spec);
Ok(())
}
fn get_spec() -> eyre::Result<openapi::OpenApiV2> {
let path = std::env::var_os("FORGEJO_API_SPEC_PATH")
.unwrap_or_else(|| OsString::from("./api_spec.json"));
let file = std::fs::read(path)?;
let spec = serde_json::from_slice::<openapi::OpenApiV2>(&file)?;
Ok(spec)
}

338
generator/src/openapi.rs Normal file
View file

@ -0,0 +1,338 @@
use std::collections::BTreeMap;
use url::Url;
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct OpenApiV2 {
pub swagger: String,
pub info: SpecInfo,
pub host: Option<Url>,
pub base_path: Option<String>,
pub schemes: Option<Vec<String>>,
pub consumes: Option<Vec<String>>,
pub produces: Option<Vec<String>>,
pub paths: BTreeMap<String, PathItem>,
pub definitions: Option<BTreeMap<String, Schema>>,
pub parameters: Option<BTreeMap<String, Parameter>>,
pub responses: Option<BTreeMap<String, Response>>,
pub security_definitions: Option<BTreeMap<String, SecurityScheme>>,
pub security: Option<Vec<BTreeMap<String, Vec<String>>>>,
pub tags: Option<Vec<Tag>>,
pub external_docs: Option<ExternalDocs>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct SpecInfo {
pub title: String,
pub description: Option<String>,
pub terms_of_service: Option<String>,
pub contact: Option<Contact>,
pub license: Option<License>,
pub version: String,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Contact {
pub name: Option<String>,
pub url: Option<String>,
pub email: Option<String>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct License {
pub name: String,
pub url: Option<Url>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct PathItem {
#[serde(rename = "$ref")]
pub _ref: Option<String>,
pub get: Option<Operation>,
pub put: Option<Operation>,
pub post: Option<Operation>,
pub delete: Option<Operation>,
pub options: Option<Operation>,
pub head: Option<Operation>,
pub patch: Option<Operation>,
pub parameters: Option<Vec<MaybeRef<Parameter>>>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Operation {
pub tags: Option<Vec<String>>,
pub summary: Option<String>,
pub description: Option<String>,
pub external_docs: Option<ExternalDocs>,
pub operation_id: Option<String>,
pub consumes: Option<Vec<String>>,
pub produces: Option<Vec<String>>,
pub parameters: Option<Vec<MaybeRef<Parameter>>>,
pub responses: Responses,
pub schemes: Option<Vec<String>>,
pub deprecated: Option<bool>,
pub security: Option<Vec<BTreeMap<String, Vec<String>>>>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct ExternalDocs {
pub description: Option<String>,
pub url: Url,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Parameter {
pub name: String,
#[serde(rename = "in")]
pub _in: String,
pub description: Option<String>,
pub required: Option<bool>,
pub schema: Option<MaybeRef<Schema>>,
#[serde(rename = "type")]
pub _type: Option<ParameterType>,
pub format: Option<String>,
pub allow_empty_value: Option<bool>,
pub items: Option<Items>,
pub collection_format: Option<CollectionFormat>,
pub default: Option<serde_json::Value>,
pub maximum: Option<f64>,
pub exclusive_maximum: Option<bool>,
pub minimum: Option<f64>,
pub exclusive_minimum: Option<bool>,
pub max_length: Option<u64>,
pub min_length: Option<u64>,
pub pattern: Option<String>, // should be regex
pub max_items: Option<u64>,
pub min_items: Option<u64>,
pub unique_items: Option<bool>,
#[serde(rename = "enum")]
pub _enum: Option<Vec<serde_json::Value>>,
pub multiple_of: Option<u64>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub enum ParameterType {
String,
Number,
Integer,
Boolean,
Array,
File,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub enum CollectionFormat {
Csv,
Ssv,
Tsv,
Pipes,
Multi,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Items {
#[serde(rename = "type")]
pub _type: ParameterType,
pub format: Option<String>,
pub items: Option<Box<Items>>,
pub collection_format: Option<CollectionFormat>,
pub default: Option<serde_json::Value>,
pub maximum: Option<f64>,
pub exclusive_maximum: Option<bool>,
pub minimum: Option<f64>,
pub exclusive_minimum: Option<bool>,
pub max_length: Option<u64>,
pub min_length: Option<u64>,
pub pattern: Option<String>, // should be regex
pub max_items: Option<u64>,
pub min_items: Option<u64>,
pub unique_items: Option<bool>,
#[serde(rename = "enum")]
pub _enum: Option<Vec<serde_json::Value>>,
pub multiple_of: Option<u64>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Responses {
pub default: Option<MaybeRef<Response>>,
#[serde(flatten)]
pub http_codes: BTreeMap<String, MaybeRef<Response>>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Response {
pub description: String,
pub schema: Option<Schema>,
pub headers: Option<BTreeMap<String, Header>>,
pub examples: Option<BTreeMap<String, serde_json::Value>>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Header {
pub description: Option<String>,
#[serde(rename = "type")]
pub _type: ParameterType,
pub format: Option<String>,
pub items: Option<Items>,
pub collection_format: Option<CollectionFormat>,
pub default: Option<serde_json::Value>,
pub maximum: Option<f64>,
pub exclusive_maximum: Option<bool>,
pub minimum: Option<f64>,
pub exclusive_minimum: Option<bool>,
pub max_length: Option<u64>,
pub min_length: Option<u64>,
pub pattern: Option<String>, // should be regex
pub max_items: Option<u64>,
pub min_items: Option<u64>,
pub unique_items: Option<bool>,
#[serde(rename = "enum")]
pub _enum: Option<Vec<serde_json::Value>>,
pub multiple_of: Option<u64>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Tag {
pub name: String,
pub description: Option<String>,
pub external_docs: Option<ExternalDocs>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Schema {
pub format: Option<String>,
pub title: Option<String>,
pub description: Option<String>,
pub default: Option<serde_json::Value>,
pub multiple_of: Option<u64>,
pub maximum: Option<f64>,
pub exclusive_maximum: Option<bool>,
pub minimum: Option<f64>,
pub exclusive_minimum: Option<bool>,
pub max_length: Option<u64>,
pub min_length: Option<u64>,
pub pattern: Option<String>, // should be regex
pub max_items: Option<u64>,
pub min_items: Option<u64>,
pub unique_items: Option<bool>,
pub max_properties: Option<u64>,
pub min_properties: Option<u64>,
pub required: Option<Vec<String>>,
#[serde(rename = "enum")]
pub _enum: Option<Vec<serde_json::Value>>,
#[serde(rename = "type")]
pub _type: Option<SchemaType>,
pub discriminator: Option<String>,
pub read_only: Option<bool>,
pub xml: Option<Xml>,
pub external_docs: Option<ExternalDocs>,
pub example: Option<serde_json::Value>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum SchemaType {
One(Primitive),
List(Vec<Primitive>),
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub enum Primitive {
Array,
Boolean,
Integer,
Number,
Null,
Object,
String,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Xml {
pub name: Option<String>,
pub namespace: Option<Url>,
pub prefix: Option<String>,
pub attribute: Option<bool>,
pub wrapped: Option<bool>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct SecurityScheme {
#[serde(flatten)]
pub _type: SecurityType,
pub description: Option<String>,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"), tag = "type")]
pub enum SecurityType {
Basic,
ApiKey {
name: String,
#[serde(rename = "in")]
_in: KeyIn,
},
OAuth2 {
#[serde(flatten)]
flow: OAuth2Flow,
scopes: BTreeMap<String, String>,
}
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"))]
pub enum KeyIn {
Query,
Header,
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(rename_all(deserialize = "camelCase"), tag = "flow")]
pub enum OAuth2Flow {
Implicit {
authorization_url: Url,
},
Password{
token_url: Url,
},
Application{
token_url: Url,
},
AccessCode{
authorization_url: Url,
token_url: Url,
},
}
#[derive(serde::Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum MaybeRef<T> {
Value {
#[serde(flatten)]
value: T,
},
Ref {
#[serde(rename = "$ref")]
_ref: String,
}
}