chore: update everything to work with utoipa

This commit is contained in:
Zomatree
2025-11-13 23:06:41 +00:00
parent 27ea7345ea
commit ac60b2c795
148 changed files with 1200 additions and 1117 deletions

View File

@@ -15,7 +15,7 @@ mongodb = ["dep:mongodb", "bson", "authifier/database-mongodb"]
# ... Other
tasks = ["isahc", "linkify", "url-escape"]
async-std-runtime = ["async-std", "authifier/async-std-runtime"]
rocket-impl = ["rocket", "schemars", "revolt_okapi", "revolt_rocket_okapi", "authifier/rocket_impl"]
rocket-impl = ["rocket"]
axum-impl = ["axum"]
redis-is-patched = ["revolt-presence/redis-is-patched"]
@@ -46,7 +46,7 @@ ulid = "1.0.0"
nanoid = "0.4.0"
base64 = "0.21.3"
once_cell = "1.17"
indexmap = "1.9.1"
indexmap = "2.12.0"
decancer = "1.6.2"
deadqueue = "0.2.4"
linkify = { optional = true, version = "0.8.1" }
@@ -58,7 +58,7 @@ isahc = { optional = true, version = "1.7", features = ["json"] }
serde_json = "1"
revolt_optional_struct = "0.2.0"
serde = { version = "1", features = ["derive"] }
iso8601-timestamp = { version = "0.2.10", features = ["serde", "bson"] }
iso8601-timestamp = { version = "0.4.0", features = ["serde", "bson"] }
# Events
redis-kiss = { version = "0.1.4" }
@@ -81,15 +81,15 @@ async-recursion = "1.0.4"
async-std = { version = "1.8.0", features = ["attributes"], optional = true }
# Axum Impl
axum = { version = "0.7.5", optional = true }
axum = { version = "0.8.6", optional = true }
# Rocket Impl
schemars = { version = "0.8.8", optional = true }
rocket = { version = "0.5.1", default-features = false, features = [
"json",
], optional = true }
revolt_okapi = { version = "0.9.1", optional = true }
revolt_rocket_okapi = { version = "0.10.0", optional = true }
# Openapi Schema
utoipa = { version = "5.4.0", optional = true }
# Authifier
authifier = { version = "1.0.15" }

View File

@@ -247,7 +247,7 @@ impl AbstractMessages for ReferenceDb {
let mut messages = self.messages.lock().await;
if let Some(message) = messages.get_mut(id) {
if let Some(users) = message.reactions.get_mut(emoji) {
users.remove(&user.to_string());
users.swap_remove(&user.to_string());
}
Ok(())
@@ -260,7 +260,7 @@ impl AbstractMessages for ReferenceDb {
async fn clear_reaction(&self, id: &str, emoji: &str) -> Result<()> {
let mut messages = self.messages.lock().await;
if let Some(message) = messages.get_mut(id) {
message.reactions.remove(emoji);
message.reactions.swap_remove(emoji);
Ok(())
} else {
Err(create_error!(NotFound))

View File

@@ -4,7 +4,6 @@ use revolt_result::{create_error, Error, Result};
use crate::{Database, User};
#[async_trait::async_trait]
impl<S> FromRequestParts<S> for User
where
Database: FromRef<S>,

View File

@@ -4,8 +4,6 @@ mod model;
mod ops;
#[cfg(feature = "rocket-impl")]
mod rocket;
#[cfg(feature = "rocket-impl")]
mod schema;
pub use model::*;
pub use ops::*;

View File

@@ -1,31 +0,0 @@
use revolt_okapi::openapi3::{SecurityScheme, SecuritySchemeData};
use revolt_rocket_okapi::{
gen::OpenApiGenerator,
request::{OpenApiFromRequest, RequestHeaderInput},
};
use crate::User;
impl OpenApiFromRequest<'_> for User {
fn from_request_input(
_gen: &mut OpenApiGenerator,
_name: String,
_required: bool,
) -> revolt_rocket_okapi::Result<RequestHeaderInput> {
let mut requirements = schemars::Map::new();
requirements.insert("Session Token".to_owned(), vec![]);
Ok(RequestHeaderInput::Security(
"Session Token".to_owned(),
SecurityScheme {
data: SecuritySchemeData::ApiKey {
name: "x-session-token".to_owned(),
location: "header".to_owned(),
},
description: Some("Used to authenticate as a user.".to_owned()),
extensions: schemars::Map::new(),
},
requirements,
))
}
}

View File

@@ -43,45 +43,45 @@ impl IdempotencyKey {
}
}
#[cfg(feature = "rocket-impl")]
use revolt_rocket_okapi::{
gen::OpenApiGenerator,
request::{OpenApiFromRequest, RequestHeaderInput},
revolt_okapi::openapi3::{Parameter, ParameterValue},
};
// #[cfg(feature = "rocket-impl")]
// use revolt_rocket_okapi::{
// gen::OpenApiGenerator,
// request::{OpenApiFromRequest, RequestHeaderInput},
// revolt_okapi::openapi3::{Parameter, ParameterValue},
// };
#[cfg(feature = "rocket-impl")]
use schemars::schema::{InstanceType, SchemaObject, SingleOrVec};
// #[cfg(feature = "rocket-impl")]
// use schemars::schema::{InstanceType, SchemaObject, SingleOrVec};
#[cfg(feature = "rocket-impl")]
impl OpenApiFromRequest<'_> for IdempotencyKey {
fn from_request_input(
_gen: &mut OpenApiGenerator,
_name: String,
_required: bool,
) -> revolt_rocket_okapi::Result<RequestHeaderInput> {
Ok(RequestHeaderInput::Parameter(Parameter {
name: "Idempotency-Key".to_string(),
description: Some("Unique key to prevent duplicate requests".to_string()),
allow_empty_value: false,
required: false,
deprecated: false,
extensions: schemars::Map::new(),
location: "header".to_string(),
value: ParameterValue::Schema {
allow_reserved: false,
example: None,
examples: None,
explode: None,
style: None,
schema: SchemaObject {
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
..Default::default()
},
},
}))
}
}
// #[cfg(feature = "rocket-impl")]
// impl OpenApiFromRequest<'_> for IdempotencyKey {
// fn from_request_input(
// _gen: &mut OpenApiGenerator,
// _name: String,
// _required: bool,
// ) -> revolt_rocket_okapi::Result<RequestHeaderInput> {
// Ok(RequestHeaderInput::Parameter(Parameter {
// name: "Idempotency-Key".to_string(),
// description: Some("Unique key to prevent duplicate requests".to_string()),
// allow_empty_value: false,
// required: false,
// deprecated: false,
// extensions: schemars::Map::new(),
// location: "header".to_string(),
// value: ParameterValue::Schema {
// allow_reserved: false,
// example: None,
// examples: None,
// explode: None,
// style: None,
// schema: SchemaObject {
// instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
// ..Default::default()
// },
// },
// }))
// }
// }
#[cfg(feature = "rocket-impl")]
use rocket::{

View File

@@ -4,3 +4,5 @@ pub mod idempotency;
pub mod permissions;
pub mod reference;
pub mod test_fixtures;
#[cfg(feature = "utoipa")]
pub mod utoipa;

View File

@@ -3,10 +3,13 @@ use std::str::FromStr;
use revolt_result::Result;
#[cfg(feature = "rocket-impl")]
use rocket::request::FromParam;
#[cfg(feature = "rocket-impl")]
use schemars::{
schema::{InstanceType, Schema, SchemaObject, SingleOrVec},
JsonSchema,
#[cfg(feature = "utoipa")]
use utoipa::{
openapi::{
path::{Parameter, ParameterBuilder, ParameterIn},
Required,
},
IntoParams,
};
use crate::{
@@ -113,16 +116,14 @@ impl<'r> FromParam<'r> for Reference<'r> {
}
}
#[cfg(feature = "rocket-impl")]
impl<'a> JsonSchema for Reference<'a> {
fn schema_name() -> String {
"Id".to_string()
}
fn json_schema(_gen: &mut schemars::gen::SchemaGenerator) -> Schema {
Schema::Object(SchemaObject {
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
..Default::default()
})
#[cfg(feature = "utoipa")]
impl IntoParams for Reference<'_> {
fn into_params(parameter_in_provider: impl Fn() -> Option<ParameterIn>) -> Vec<Parameter> {
vec![ParameterBuilder::new()
.name("id")
.required(Required::True)
.description(Some("An ID".to_string()))
.parameter_in(parameter_in_provider().unwrap_or_default())
.build()]
}
}

View File

@@ -0,0 +1,21 @@
use utoipa::{Modify, openapi::{OpenApi, security::{ApiKey, ApiKeyValue, SecurityScheme}}};
pub struct TokenSecurity;
impl Modify for TokenSecurity {
fn modify(&self, openapi: &mut OpenApi) {
let components = openapi.components.get_or_insert_default();
components.add_security_scheme(
"Session-Token",
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::new(
"X-Session-Token".to_string(),
))),
);
components.add_security_scheme(
"Bot-Token",
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::new("X-Bot-Ticket".to_string()))),
);
}
}

View File

@@ -10,22 +10,22 @@ description = "Revolt Backend: API Models"
[features]
serde = ["dep:serde", "revolt-permissions/serde", "indexmap/serde"]
schemas = ["dep:schemars", "revolt-permissions/schemas"]
utoipa = ["dep:utoipa"]
validator = ["dep:validator"]
rocket = ["dep:rocket"]
partials = ["dep:revolt_optional_struct", "serde", "schemas", "utoipa"]
partials = ["dep:revolt_optional_struct", "serde", "utoipa"]
default = ["serde", "partials", "rocket"]
[dependencies]
# Core
revolt-config = { version = "0.8.9", path = "../config" }
revolt-permissions = { version = "0.8.9", path = "../permissions" }
revolt-permissions = { version = "0.8.9", path = "../permissions", features = [
"utoipa",
] }
# Utility
regex = "1.11"
indexmap = "1.9.3"
indexmap = "2.12.0"
once_cell = "1.17.1"
num_enum = "0.6.1"
@@ -35,11 +35,10 @@ rocket = { optional = true, version = "0.5.0-rc.2", default-features = false }
# Serialisation
revolt_optional_struct = { version = "0.2.0", optional = true }
serde = { version = "1", features = ["derive"], optional = true }
iso8601-timestamp = { version = "0.2.11", features = ["schema", "bson"] }
iso8601-timestamp = { version = "0.4.0", features = ["utoipa", "bson"] }
# Spec Generation
schemars = { version = "0.8.8", optional = true, features = ["indexmap1"] }
utoipa = { version = "4.2.3", optional = true }
utoipa = { version = "5.4.0", features = ["indexmap"], optional = true }
# Validation
validator = { version = "0.16.0", optional = true, features = ["derive"] }

View File

@@ -2,10 +2,6 @@
#[macro_use]
extern crate serde;
#[cfg(feature = "schemas")]
#[macro_use]
extern crate schemars;
#[cfg(feature = "utoipa")]
#[macro_use]
extern crate utoipa;
@@ -21,7 +17,6 @@ macro_rules! auto_derived {
( $( $item:item )+ ) => {
$(
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "schemas", derive(JsonSchema))]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[derive(Debug, Clone, Eq, PartialEq)]
$item
@@ -32,19 +27,8 @@ macro_rules! auto_derived {
#[cfg(feature = "partials")]
macro_rules! auto_derived_partial {
( $item:item, $name:expr ) => {
#[derive(
OptionalStruct, Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema,
)]
#[optional_derive(
Debug,
Clone,
Eq,
PartialEq,
Serialize,
Deserialize,
JsonSchema,
Default
)]
#[derive(OptionalStruct, Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ToSchema)]
#[optional_derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ToSchema, Default)]
#[optional_name = $name]
#[opt_skip_serializing_none]
#[opt_some_priority]
@@ -55,7 +39,7 @@ macro_rules! auto_derived_partial {
#[cfg(not(feature = "partials"))]
macro_rules! auto_derived_partial {
( $item:item, $name:expr ) => {
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ToSchema)]
$item
};
}

View File

@@ -86,10 +86,10 @@ auto_derived!(
/// Information for the webhook
#[cfg_attr(feature = "validator", derive(Validate))]
pub struct CreateWebhookBody {
#[validate(length(min = 1, max = 32))]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
pub name: String,
#[validate(length(min = 1, max = 128))]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 128)))]
pub avatar: Option<String>,
}
);

View File

@@ -0,0 +1,73 @@
auto_derived!(
/// # hCaptcha Configuration
pub struct CaptchaFeature {
/// Whether captcha is enabled
pub enabled: bool,
/// Client key used for solving captcha
pub key: String,
}
/// # Generic Service Configuration
pub struct Feature {
/// Whether the service is enabled
pub enabled: bool,
/// URL pointing to the service
pub url: String,
}
/// # Voice Server Configuration
pub struct VoiceFeature {
/// Whether voice is enabled
pub enabled: bool,
/// URL pointing to the voice API
pub url: String,
/// URL pointing to the voice WebSocket server
pub ws: String,
}
/// # Feature Configuration
pub struct RevoltFeatures {
/// hCaptcha configuration
pub captcha: CaptchaFeature,
/// Whether email verification is enabled
pub email: bool,
/// Whether this server is invite only
pub invite_only: bool,
/// File server service configuration
pub autumn: Feature,
/// Proxy service configuration
pub january: Feature,
/// Voice server configuration
pub voso: VoiceFeature,
}
/// # Build Information
pub struct BuildInformation {
/// Commit Hash
pub commit_sha: String,
/// Commit Timestamp
pub commit_timestamp: String,
/// Git Semver
pub semver: String,
/// Git Origin URL
pub origin_url: String,
/// Build Timestamp
pub timestamp: String,
}
/// # Server Configuration
pub struct RevoltConfig {
/// Revolt API Version
pub revolt: String,
/// Features enabled on this Revolt node
pub features: RevoltFeatures,
/// WebSocket URL
pub ws: String,
/// URL pointing to the client serving this node
pub app: String,
/// Web Push VAPID public key
pub vapid: String,
/// Build information
pub build: BuildInformation,
}
);

View File

@@ -46,7 +46,7 @@ auto_derived!(
#[cfg_attr(feature = "validator", derive(Validate))]
pub struct DataCreateEmoji {
/// Server name
#[validate(length(min = 1, max = 32), regex = "RE_EMOJI")]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32), regex = "RE_EMOJI"))]
pub name: String,
/// Parent information
pub parent: EmojiParent,

View File

@@ -139,17 +139,17 @@ auto_derived!(
pub struct Masquerade {
/// Replace the display name shown on this message
#[serde(skip_serializing_if = "Option::is_none")]
#[validate(length(min = 1, max = 32))]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
pub name: Option<String>,
/// Replace the avatar shown on this message (URL to image file)
#[serde(skip_serializing_if = "Option::is_none")]
#[validate(length(min = 1, max = 256))]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 256)))]
pub avatar: Option<String>,
/// Replace the display role colour shown on this message
///
/// Must have `ManageRole` permission to use
#[serde(skip_serializing_if = "Option::is_none")]
#[validate(length(min = 1, max = 128), regex = "RE_COLOUR")]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 128), regex = "RE_COLOUR"))]
pub colour: Option<String>,
}
@@ -351,7 +351,7 @@ auto_derived!(
)]
pub struct OptionsBulkDelete {
/// Message IDs
#[validate(length(min = 1, max = 100))]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 100)))]
pub ids: Vec<String>,
}

View File

@@ -3,6 +3,7 @@ mod channel_invites;
mod channel_unreads;
mod channel_webhooks;
mod channels;
mod config;
mod embeds;
mod emojis;
mod files;
@@ -20,6 +21,7 @@ pub use channel_invites::*;
pub use channel_unreads::*;
pub use channel_webhooks::*;
pub use channels::*;
pub use config::*;
pub use embeds::*;
pub use emojis::*;
pub use files::*;

View File

@@ -141,7 +141,7 @@ auto_derived!(
#[cfg_attr(feature = "validator", derive(Validate))]
pub struct UserStatus {
/// Custom status text
#[validate(length(min = 0, max = 128))]
#[cfg_attr(feature = "validator", validate(length(min = 0, max = 128)))]
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub text: Option<String>,
/// Current presence option
@@ -154,7 +154,7 @@ auto_derived!(
#[cfg_attr(feature = "validator", derive(Validate))]
pub struct UserProfile {
/// Text content on user's profile
#[validate(length(min = 0, max = 2000))]
#[cfg_attr(feature = "validator", validate(length(min = 0, max = 2000)))]
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub content: Option<String>,
/// Background visible on user's profile

View File

@@ -11,10 +11,8 @@ description = "Revolt Backend: Permission Logic"
[features]
bson = ["dep:bson"]
serde = ["dep:serde"]
schemas = ["dep:schemars"]
try-from-primitive = ["dep:num_enum"]
[dev-dependencies]
# Async
async-std = { version = "1.8.0", features = ["attributes"] }
@@ -36,4 +34,4 @@ serde = { version = "1", features = ["derive"], optional = true }
bson = { version = "2.1.0", optional = true }
# Spec Generation
schemars = { version = "0.8.8", optional = true }
utoipa = { version = "5.4.0", optional = true }

View File

@@ -1,10 +1,10 @@
#[cfg(feature = "schemas")]
use schemars::JsonSchema;
#[cfg(feature = "utoipa")]
use utoipa::ToSchema;
/// Representation of a single permission override
#[derive(Debug, Clone, Eq, PartialEq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "schemas", derive(JsonSchema))]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct Override {
/// Allow bit flags
pub allow: u64,
@@ -15,7 +15,7 @@ pub struct Override {
/// Data permissions Field - contains both allow and deny
#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "schemas", derive(JsonSchema))]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct DataPermissionsField {
pub permissions: Override,
}
@@ -23,7 +23,7 @@ pub struct DataPermissionsField {
/// Data permissions Value - contains allow
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "schemas", derive(JsonSchema))]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct DataPermissionsValue {
pub permissions: u64,
}
@@ -31,7 +31,7 @@ pub struct DataPermissionsValue {
/// Data permissions Poly - can contain either Value or Field
#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "schemas", derive(JsonSchema))]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[cfg_attr(feature = "serde", serde(untagged))]
pub enum DataPermissionPoly {
Value {
@@ -48,7 +48,7 @@ pub enum DataPermissionPoly {
/// as it appears on models and in the database
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "schemas", derive(JsonSchema))]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct OverrideField {
/// Allow bit flags
pub a: i64,

View File

@@ -4,20 +4,24 @@ version = "0.8.9"
edition = "2024"
[features]
rocket = ["dep:rocket", "dep:revolt_rocket_okapi", "revolt-database/rocket-impl"]
rocket = [
"dep:rocket",
"dep:revolt_rocket_okapi",
"revolt-database/rocket-impl",
]
axum = ["dep:axum", "revolt-database/axum-impl"]
default = ["rocket", "axum"]
[dependencies]
revolt-database = { version = "0.8.9", path = "../database"}
revolt-database = { version = "0.8.9", path = "../database" }
revolt-result = { version = "0.8.9", path = "../result" }
revolt-config = { version = "0.8.9", path = "../config" }
rocket = { version = "0.5.1", optional = true }
revolt_rocket_okapi = { version = "0.10.0", optional = true }
axum = { version = "0.7.5", optional = true, features = ["macros"] }
axum = { version = "0.8.6", optional = true, features = ["macros"] }
serde = { version = "1", features = ["derive"] }
authifier = { version = "1.0.15" }

View File

@@ -1,6 +1,5 @@
use std::net::SocketAddr;
use async_trait::async_trait;
use axum::{
Json, RequestPartsExt, Router,
body::Body,
@@ -44,7 +43,6 @@ async fn to_real_ip(parts: &Parts) -> String {
}
}
#[async_trait]
impl<S: Send + Sync> FromRequestParts<S> for Ratelimiter
where
Database: FromRef<S>,
@@ -82,7 +80,6 @@ where
}
}
#[async_trait]
impl<S: Send + Sync> FromRequestParts<S> for RatelimitInformation
where
Database: FromRef<S>,

View File

@@ -10,11 +10,9 @@ description = "Revolt Backend: Result and Error types"
[features]
serde = ["dep:serde"]
schemas = ["dep:schemars"]
utoipa = ["dep:utoipa"]
rocket = ["dep:rocket", "dep:serde_json"]
axum = ["dep:axum", "dep:serde_json"]
okapi = ["dep:revolt_rocket_okapi", "dep:revolt_okapi", "schemas"]
default = ["serde"]
@@ -24,13 +22,10 @@ serde_json = { version = "1", optional = true }
serde = { version = "1", features = ["derive"], optional = true }
# Spec Generation
schemars = { version = "0.8.8", optional = true }
utoipa = { version = "4.2.3", optional = true }
utoipa = { version = "5.4.0", optional = true }
# Rocket
rocket = { optional = true, version = "0.5.0-rc.2", default-features = false }
revolt_rocket_okapi = { version = "0.10.0", optional = true }
revolt_okapi = { version = "0.9.1", optional = true }
# Axum
axum = { version = "0.7.5", optional = true }
axum = { version = "0.8.6", optional = true }

View File

@@ -4,10 +4,6 @@ use std::fmt::Display;
#[macro_use]
extern crate serde;
#[cfg(feature = "schemas")]
#[macro_use]
extern crate schemars;
#[cfg(feature = "utoipa")]
#[macro_use]
extern crate utoipa;
@@ -18,15 +14,11 @@ pub mod rocket;
#[cfg(feature = "axum")]
pub mod axum;
#[cfg(feature = "okapi")]
pub mod okapi;
/// Result type with custom Error
pub type Result<T, E = Error> = std::result::Result<T, E>;
/// Error information
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "schemas", derive(JsonSchema))]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[derive(Debug, Clone)]
pub struct Error {
@@ -49,7 +41,6 @@ impl std::error::Error for Error {}
/// Possible error types
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type"))]
#[cfg_attr(feature = "schemas", derive(JsonSchema))]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[derive(Debug, Clone)]
pub enum ErrorType {

View File

@@ -1,49 +0,0 @@
use revolt_okapi::openapi3::SchemaObject;
use revolt_rocket_okapi::revolt_okapi::openapi3;
use schemars::schema::Schema;
use crate::Error;
impl revolt_rocket_okapi::response::OpenApiResponderInner for Error {
fn responses(
gen: &mut revolt_rocket_okapi::gen::OpenApiGenerator,
) -> std::result::Result<openapi3::Responses, revolt_rocket_okapi::OpenApiError> {
let mut content = revolt_okapi::Map::new();
let settings = schemars::gen::SchemaSettings::default().with(|s| {
s.option_nullable = true;
s.option_add_null_type = false;
s.definitions_path = "#/components/schemas/".to_string();
});
let mut schema_generator = settings.into_generator();
let schema = schema_generator.root_schema_for::<Error>();
let definitions = gen.schema_generator().definitions_mut();
for (key, value) in schema.definitions {
definitions.insert(key, value);
}
definitions.insert("Error".to_string(), Schema::Object(schema.schema));
content.insert(
"application/json".to_string(),
openapi3::MediaType {
schema: Some(SchemaObject {
reference: Some("#/components/schemas/Error".to_string()),
..Default::default()
}),
..Default::default()
},
);
Ok(openapi3::Responses {
default: Some(openapi3::RefOr::Object(openapi3::Response {
content,
description: "An error occurred.".to_string(),
..Default::default()
})),
..Default::default()
})
}
}