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

54
Cargo.lock generated
View file

@ -136,9 +136,9 @@ dependencies = [
[[package]]
name = "eyre"
version = "0.6.9"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd"
checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799"
dependencies = [
"indenter",
"once_cell",
@ -191,9 +191,9 @@ dependencies = [
[[package]]
name = "form_urlencoded"
version = "1.2.0"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
@ -237,6 +237,16 @@ dependencies = [
"pin-utils",
]
[[package]]
name = "generator"
version = "0.1.0"
dependencies = [
"eyre",
"serde",
"serde_json",
"url",
]
[[package]]
name = "gimli"
version = "0.28.0"
@ -341,9 +351,9 @@ dependencies = [
[[package]]
name = "idna"
version = "0.4.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
@ -531,9 +541,9 @@ dependencies = [
[[package]]
name = "percent-encoding"
version = "2.3.0"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project-lite"
@ -561,18 +571,18 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "proc-macro2"
version = "1.0.69"
version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@ -684,18 +694,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.192"
version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.192"
version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
dependencies = [
"proc-macro2",
"quote",
@ -704,9 +714,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.108"
version = "1.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
dependencies = [
"itoa",
"ryu",
@ -762,9 +772,9 @@ checksum = "b5097ec7ea7218135541ad96348f1441d0c616537dd4ed9c47205920c35d7d97"
[[package]]
name = "syn"
version = "2.0.39"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
@ -983,9 +993,9 @@ dependencies = [
[[package]]
name = "url"
version = "2.4.1"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
"form_urlencoded",
"idna",

View file

@ -1,3 +1,4 @@
workspace = { members = ["generator"] }
[package]
name = "forgejo-api"
version = "0.1.0"

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,
}
}

24321
swagger.v1.json Normal file

File diff suppressed because it is too large Load diff