mirror of
https://github.com/modrinth/code.git
synced 2026-09-03 13:36:48 +00:00
feat: better api docs (#6586)
* feat: docs * fix tombi * chore: fix some of the routes rendering with missing / * response schemas * fix: restore labrinth docs routes * Fix path parameter docs in routes * remove utoipa-actix-web * consistency * improve version intros * improve formatting, examples * better hash examples, move openapi stuff to openapi.rs * more utoipa param fixes * request body docs * chore: remove moderation route from v2, remove ingest & webhooks from v3 spec * fixes * chore: tweak sources titles * fix * fix test * improve examples * increase compiler spawned thread stack size * remove unused tests & script * test * bro what * fix --------- Co-authored-by: aecsocket <43144841+aecsocket@users.noreply.github.com>
This commit is contained in:
co-authored by
aecsocket
parent
b26d048a63
commit
4a6fa9fc3d
@@ -19,13 +19,13 @@ use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use validator::Validate;
|
||||
|
||||
pub fn config(cfg: &mut utoipa_actix_web::service_config::ServiceConfig) {
|
||||
pub fn config(cfg: &mut actix_web::web::ServiceConfig) {
|
||||
cfg.service(project_search);
|
||||
cfg.service(projects_get);
|
||||
cfg.service(projects_edit);
|
||||
cfg.service(random_projects_get);
|
||||
cfg.service(
|
||||
utoipa_actix_web::scope("/project")
|
||||
web::scope("/project")
|
||||
.service(project_get)
|
||||
.service(project_get_check)
|
||||
.service(project_delete)
|
||||
@@ -39,7 +39,7 @@ pub fn config(cfg: &mut utoipa_actix_web::service_config::ServiceConfig) {
|
||||
.service(project_unfollow)
|
||||
.service(super::teams::team_members_get_project)
|
||||
.service(
|
||||
utoipa_actix_web::scope("/{project_id}")
|
||||
web::scope("/{project_id}")
|
||||
.service(super::versions::version_list)
|
||||
.service(super::versions::version_project_get)
|
||||
.service(dependency_list),
|
||||
@@ -47,39 +47,25 @@ pub fn config(cfg: &mut utoipa_actix_web::service_config::ServiceConfig) {
|
||||
);
|
||||
}
|
||||
|
||||
/// Search projects.
|
||||
/// Search projects.
|
||||
#[utoipa::path(
|
||||
tag = "search",
|
||||
get,
|
||||
operation_id = "searchProjects",
|
||||
params(
|
||||
(
|
||||
"query" = Option<String>,
|
||||
Query,
|
||||
description = "The query to search for"
|
||||
),
|
||||
(
|
||||
"facets" = Option<String>,
|
||||
Query,
|
||||
description = "Search facets JSON"
|
||||
),
|
||||
(
|
||||
"index" = Option<String>,
|
||||
Query,
|
||||
description = "Search index to use"
|
||||
),
|
||||
(
|
||||
"offset" = Option<String>,
|
||||
Query,
|
||||
description = "Search result offset"
|
||||
),
|
||||
(
|
||||
"limit" = Option<String>,
|
||||
Query,
|
||||
description = "Maximum number of search results"
|
||||
)
|
||||
("query" = Option<String>, Query, description = "The query to search for"),
|
||||
("facets" = Option<String>, Query, description = "Search facets JSON"),
|
||||
("index" = Option<String>, Query, description = "Search index to use"),
|
||||
("offset" = Option<String>, Query, description = "Search result offset"),
|
||||
("limit" = Option<String>, Query, description = "Maximum number of search results"),
|
||||
("show_metadata" = Option<bool>, Query, description = "Whether to include search metadata"),
|
||||
("typesense_config" = Option<String>, Query, description = "Typesense request configuration"),
|
||||
("new_filters" = Option<String>, Query, description = "Search filters"),
|
||||
("filters" = Option<String>, Query, description = "Legacy search filters"),
|
||||
("version" = Option<String>, Query, description = "Legacy search version")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Expected response to a valid request"),
|
||||
(status = 200, description = "Expected response to a valid request", body = LegacySearchResults),
|
||||
(status = 400, description = "Request was invalid, see given error")
|
||||
)
|
||||
)]
|
||||
@@ -180,19 +166,16 @@ pub struct RandomProjects {
|
||||
pub count: u32,
|
||||
}
|
||||
|
||||
/// Get random projects.
|
||||
/// Get random projects.
|
||||
#[utoipa::path(
|
||||
tag = "projects",
|
||||
get,
|
||||
operation_id = "randomProjects",
|
||||
params(
|
||||
(
|
||||
"count" = u32,
|
||||
Query,
|
||||
description = "Number of projects to return"
|
||||
)
|
||||
("count" = u32, Query, description = "Number of projects to return")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Expected response to a valid request"),
|
||||
(status = 200, description = "Expected response to a valid request", body = Vec<LegacyProject>),
|
||||
(status = 400, description = "Request was invalid, see given error")
|
||||
)
|
||||
)]
|
||||
@@ -223,18 +206,15 @@ pub async fn random_projects_get(
|
||||
}
|
||||
}
|
||||
|
||||
/// Get multiple projects by ID or slug.
|
||||
/// Get multiple projects by ID or slug.
|
||||
#[utoipa::path(
|
||||
tag = "projects",
|
||||
get,
|
||||
operation_id = "getProjects",
|
||||
params(
|
||||
(
|
||||
"ids" = String,
|
||||
Query,
|
||||
description = "The JSON array of project IDs or slugs"
|
||||
)
|
||||
("ids" = String, Query, description = "The JSON array of project IDs or slugs")
|
||||
),
|
||||
responses((status = 200, description = "Expected response to a valid request"))
|
||||
responses((status = 200, description = "Expected response to a valid request", body = Vec<LegacyProject>))
|
||||
)]
|
||||
#[get("/projects")]
|
||||
pub async fn projects_get(
|
||||
@@ -267,13 +247,17 @@ pub async fn projects_get(
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a project by ID or slug.
|
||||
/// Get a project by ID or slug.
|
||||
#[utoipa::path(
|
||||
context_path = "/project",
|
||||
tag = "projects",
|
||||
get,
|
||||
operation_id = "getProject",
|
||||
params(("id" = String, Path, description = "The ID or slug of the project")),
|
||||
params(
|
||||
("id" = String, Path, description = "The ID or slug of the project")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Expected response to a valid request"),
|
||||
(status = 200, description = "Expected response to a valid request", body = LegacyProject),
|
||||
(
|
||||
status = 404,
|
||||
description = "The requested item(s) were not found or no authorization to access the requested item(s)"
|
||||
@@ -316,13 +300,17 @@ pub async fn project_get(
|
||||
}
|
||||
|
||||
//checks the validity of a project id or slug
|
||||
/// Check that a project ID or slug exists.
|
||||
/// Check that a project ID or slug exists.
|
||||
#[utoipa::path(
|
||||
context_path = "/project",
|
||||
tag = "projects",
|
||||
get,
|
||||
operation_id = "checkProjectValidity",
|
||||
params(("id" = String, Path, description = "The ID or slug of the project")),
|
||||
params(
|
||||
("id" = String, Path, description = "The ID or slug of the project")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Expected response to a valid request"),
|
||||
(status = 200, description = "Expected response to a valid request", body = v3::projects::ProjectCheckResponse),
|
||||
(
|
||||
status = 404,
|
||||
description = "The requested item(s) were not found or no authorization to access the requested item(s)"
|
||||
@@ -347,13 +335,17 @@ struct DependencyInfo {
|
||||
pub versions: Vec<LegacyVersion>,
|
||||
}
|
||||
|
||||
/// Get dependency projects and versions for a project.
|
||||
/// Get dependency projects and versions for a project.
|
||||
#[utoipa::path(
|
||||
context_path = "/project/{project_id}",
|
||||
tag = "projects",
|
||||
get,
|
||||
operation_id = "getDependencies",
|
||||
params(("id" = String, Path, description = "The ID or slug of the project")),
|
||||
params(
|
||||
("id" = String, Path, description = "The ID or slug of the project")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Expected response to a valid request"),
|
||||
(status = 200, description = "Expected response to a valid request", body = DependencyInfo),
|
||||
(
|
||||
status = 404,
|
||||
description = "The requested item(s) were not found or no authorization to access the requested item(s)"
|
||||
@@ -507,14 +499,18 @@ pub struct EditProject {
|
||||
pub monetization_status: Option<MonetizationStatus>,
|
||||
}
|
||||
|
||||
/// Modify a project.
|
||||
/// Update a project.
|
||||
#[utoipa::path(
|
||||
context_path = "/project",
|
||||
tag = "projects",
|
||||
patch,
|
||||
operation_id = "modifyProject",
|
||||
params(("id" = String, Path, description = "The ID or slug of the project")),
|
||||
params(
|
||||
("id" = String, Path, description = "The ID or slug of the project")
|
||||
),
|
||||
request_body = EditProject,
|
||||
responses(
|
||||
(status = 204, description = "Expected response to a valid request"),
|
||||
(status = NO_CONTENT, description = "Expected response to a valid request"),
|
||||
(
|
||||
status = 401,
|
||||
description = "Incorrect token scopes or no authorization to access the requested item(s)"
|
||||
@@ -763,20 +759,17 @@ pub struct BulkEditProject {
|
||||
pub discord_url: Option<Option<String>>,
|
||||
}
|
||||
|
||||
/// Bulk-edit multiple projects.
|
||||
/// Bulk-edit multiple projects.
|
||||
#[utoipa::path(
|
||||
tag = "projects",
|
||||
patch,
|
||||
operation_id = "patchProjects",
|
||||
params(
|
||||
(
|
||||
"ids" = String,
|
||||
Query,
|
||||
description = "The JSON array of project IDs or slugs"
|
||||
)
|
||||
("ids" = String, Query, description = "The JSON array of project IDs or slugs")
|
||||
),
|
||||
request_body = BulkEditProject,
|
||||
responses(
|
||||
(status = 204, description = "Expected response to a valid request"),
|
||||
(status = NO_CONTENT, description = "Expected response to a valid request"),
|
||||
(status = 400, description = "Request was invalid, see given error"),
|
||||
(
|
||||
status = 401,
|
||||
@@ -889,17 +882,15 @@ pub struct Extension {
|
||||
pub ext: String,
|
||||
}
|
||||
|
||||
/// Change a project's icon.
|
||||
/// Change a project's icon.
|
||||
#[utoipa::path(
|
||||
context_path = "/project",
|
||||
tag = "projects",
|
||||
patch,
|
||||
operation_id = "changeProjectIcon",
|
||||
params(
|
||||
("id" = String, Path, description = "The ID or slug of the project"),
|
||||
(
|
||||
"ext" = String,
|
||||
Query,
|
||||
description = "Image extension (png, jpg, jpeg, bmp, gif, webp, svg, svgz, rgb)"
|
||||
)
|
||||
("ext" = String, Query, description = "Image extension (png, jpg, jpeg, bmp, gif, webp, svg, svgz, rgb)")
|
||||
),
|
||||
request_body(
|
||||
content(
|
||||
@@ -912,7 +903,7 @@ pub struct Extension {
|
||||
)
|
||||
),
|
||||
responses(
|
||||
(status = 204, description = "Expected response to a valid request"),
|
||||
(status = NO_CONTENT, description = "Expected response to a valid request"),
|
||||
(status = 400, description = "Request was invalid, see given error")
|
||||
),
|
||||
security(("bearer_auth" = ["PROJECT_WRITE"]))
|
||||
@@ -946,13 +937,17 @@ pub async fn project_icon_edit(
|
||||
.or_else(v2_reroute::flatten_404_error)
|
||||
}
|
||||
|
||||
/// Delete a project's icon.
|
||||
/// Delete a project's icon.
|
||||
#[utoipa::path(
|
||||
context_path = "/project",
|
||||
tag = "projects",
|
||||
delete,
|
||||
operation_id = "deleteProjectIcon",
|
||||
params(("id" = String, Path, description = "The ID or slug of the project")),
|
||||
params(
|
||||
("id" = String, Path, description = "The ID or slug of the project")
|
||||
),
|
||||
responses(
|
||||
(status = 204, description = "Expected response to a valid request"),
|
||||
(status = NO_CONTENT, description = "Expected response to a valid request"),
|
||||
(status = 400, description = "Request was invalid, see given error"),
|
||||
(
|
||||
status = 401,
|
||||
@@ -995,37 +990,19 @@ pub struct GalleryCreateQuery {
|
||||
pub ordering: Option<i64>,
|
||||
}
|
||||
|
||||
/// Add a gallery image to a project.
|
||||
/// Add a gallery image to a project.
|
||||
#[utoipa::path(
|
||||
context_path = "/project",
|
||||
tag = "projects",
|
||||
post,
|
||||
operation_id = "addGalleryImage",
|
||||
params(
|
||||
("id" = String, Path, description = "The ID or slug of the project"),
|
||||
(
|
||||
"ext" = String,
|
||||
Query,
|
||||
description = "Image extension (png, jpg, jpeg, bmp, gif, webp, svg, svgz, rgb)"
|
||||
),
|
||||
(
|
||||
"featured" = bool,
|
||||
Query,
|
||||
description = "Whether this image is featured"
|
||||
),
|
||||
(
|
||||
"title" = Option<String>,
|
||||
Query,
|
||||
description = "Image title"
|
||||
),
|
||||
(
|
||||
"description" = Option<String>,
|
||||
Query,
|
||||
description = "Image description"
|
||||
),
|
||||
(
|
||||
"ordering" = Option<i64>,
|
||||
Query,
|
||||
description = "Image ordering"
|
||||
)
|
||||
("ext" = String, Query, description = "Image extension (png, jpg, jpeg, bmp, gif, webp, svg, svgz, rgb)"),
|
||||
("featured" = bool, Query, description = "Whether this image is featured"),
|
||||
("title" = Option<String>, Query, description = "Image title"),
|
||||
("description" = Option<String>, Query, description = "Image description"),
|
||||
("ordering" = Option<i64>, Query, description = "Image ordering")
|
||||
),
|
||||
request_body(
|
||||
content(
|
||||
@@ -1038,7 +1015,7 @@ pub struct GalleryCreateQuery {
|
||||
)
|
||||
),
|
||||
responses(
|
||||
(status = 204, description = "Expected response to a valid request"),
|
||||
(status = NO_CONTENT, description = "Expected response to a valid request"),
|
||||
(status = 400, description = "Request was invalid, see given error"),
|
||||
(
|
||||
status = 401,
|
||||
@@ -1109,36 +1086,22 @@ pub struct GalleryEditQuery {
|
||||
pub ordering: Option<i64>,
|
||||
}
|
||||
|
||||
/// Modify a gallery image.
|
||||
/// Update a gallery image.
|
||||
#[utoipa::path(
|
||||
context_path = "/project",
|
||||
tag = "projects",
|
||||
patch,
|
||||
operation_id = "modifyGalleryImage",
|
||||
params(
|
||||
("id" = String, Path, description = "The ID or slug of the project"),
|
||||
("url" = String, Query, description = "URL of the image to edit"),
|
||||
(
|
||||
"featured" = Option<bool>,
|
||||
Query,
|
||||
description = "Whether this image is featured"
|
||||
),
|
||||
(
|
||||
"title" = Option<Option<String>>,
|
||||
Query,
|
||||
description = "Image title"
|
||||
),
|
||||
(
|
||||
"description" = Option<Option<String>>,
|
||||
Query,
|
||||
description = "Image description"
|
||||
),
|
||||
(
|
||||
"ordering" = Option<i64>,
|
||||
Query,
|
||||
description = "Image ordering"
|
||||
)
|
||||
("featured" = Option<bool>, Query, description = "Whether this image is featured"),
|
||||
("title" = Option<Option<String>>, Query, description = "Image title"),
|
||||
("description" = Option<Option<String>>, Query, description = "Image description"),
|
||||
("ordering" = Option<i64>, Query, description = "Image ordering")
|
||||
),
|
||||
responses(
|
||||
(status = 204, description = "Expected response to a valid request"),
|
||||
(status = NO_CONTENT, description = "Expected response to a valid request"),
|
||||
(
|
||||
status = 401,
|
||||
description = "Incorrect token scopes or no authorization to access the requested item(s)"
|
||||
@@ -1183,8 +1146,10 @@ pub struct GalleryDeleteQuery {
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
/// Delete a gallery image.
|
||||
/// Delete a gallery image.
|
||||
#[utoipa::path(
|
||||
context_path = "/project",
|
||||
tag = "projects",
|
||||
delete,
|
||||
operation_id = "deleteGalleryImage",
|
||||
params(
|
||||
@@ -1192,7 +1157,7 @@ pub struct GalleryDeleteQuery {
|
||||
("url" = String, Query, description = "URL of the image to delete")
|
||||
),
|
||||
responses(
|
||||
(status = 204, description = "Expected response to a valid request"),
|
||||
(status = NO_CONTENT, description = "Expected response to a valid request"),
|
||||
(status = 400, description = "Request was invalid, see given error"),
|
||||
(
|
||||
status = 401,
|
||||
@@ -1225,13 +1190,17 @@ pub async fn delete_gallery_item(
|
||||
.or_else(v2_reroute::flatten_404_error)
|
||||
}
|
||||
|
||||
/// Delete a project by ID or slug.
|
||||
/// Delete a project by ID or slug.
|
||||
#[utoipa::path(
|
||||
context_path = "/project",
|
||||
tag = "projects",
|
||||
delete,
|
||||
operation_id = "deleteProject",
|
||||
params(("id" = String, Path, description = "The ID or slug of the project")),
|
||||
params(
|
||||
("id" = String, Path, description = "The ID or slug of the project")
|
||||
),
|
||||
responses(
|
||||
(status = 204, description = "Expected response to a valid request"),
|
||||
(status = NO_CONTENT, description = "Expected response to a valid request"),
|
||||
(status = 400, description = "Request was invalid, see given error"),
|
||||
(
|
||||
status = 401,
|
||||
@@ -1263,13 +1232,17 @@ pub async fn project_delete(
|
||||
.or_else(v2_reroute::flatten_404_error)
|
||||
}
|
||||
|
||||
/// Follow a project.
|
||||
/// Follow a project.
|
||||
#[utoipa::path(
|
||||
context_path = "/project",
|
||||
tag = "projects",
|
||||
post,
|
||||
operation_id = "followProject",
|
||||
params(("id" = String, Path, description = "The ID or slug of the project")),
|
||||
params(
|
||||
("id" = String, Path, description = "The ID or slug of the project")
|
||||
),
|
||||
responses(
|
||||
(status = 204, description = "Expected response to a valid request"),
|
||||
(status = NO_CONTENT, description = "Expected response to a valid request"),
|
||||
(status = 400, description = "Request was invalid, see given error"),
|
||||
(
|
||||
status = 401,
|
||||
@@ -1292,13 +1265,17 @@ pub async fn project_follow(
|
||||
.or_else(v2_reroute::flatten_404_error)
|
||||
}
|
||||
|
||||
/// Unfollow a project.
|
||||
/// Unfollow a project.
|
||||
#[utoipa::path(
|
||||
context_path = "/project",
|
||||
tag = "projects",
|
||||
delete,
|
||||
operation_id = "unfollowProject",
|
||||
params(("id" = String, Path, description = "The ID or slug of the project")),
|
||||
params(
|
||||
("id" = String, Path, description = "The ID or slug of the project")
|
||||
),
|
||||
responses(
|
||||
(status = 204, description = "Expected response to a valid request"),
|
||||
(status = NO_CONTENT, description = "Expected response to a valid request"),
|
||||
(status = 400, description = "Request was invalid, see given error"),
|
||||
(
|
||||
status = 401,
|
||||
|
||||
Reference in New Issue
Block a user