11//! Endpoint for versions of a crate
22
3- use axum:: extract:: FromRequestParts ;
4- use axum_extra:: extract:: Query ;
5- use axum_extra:: json;
6- use axum_extra:: response:: ErasedJson ;
7- use diesel:: dsl:: not;
8- use diesel:: prelude:: * ;
9- use diesel_async:: { AsyncPgConnection , RunQueryDsl } ;
10- use futures_util:: { TryStreamExt , future} ;
11- use http:: request:: Parts ;
12- use indexmap:: { IndexMap , IndexSet } ;
13- use std:: str:: FromStr ;
14-
153use crate :: app:: AppState ;
164use crate :: controllers:: helpers:: pagination:: {
175 Page , PaginationOptions , PaginationQueryParams , encode_seek,
@@ -23,6 +11,16 @@ use crate::util::RequestUtils;
2311use crate :: util:: errors:: { AppResult , BoxedAppError , bad_request} ;
2412use crate :: util:: string_excl_null:: StringExclNull ;
2513use crate :: views:: EncodableVersion ;
14+ use axum:: Json ;
15+ use axum:: extract:: FromRequestParts ;
16+ use axum_extra:: extract:: Query ;
17+ use diesel:: dsl:: not;
18+ use diesel:: prelude:: * ;
19+ use diesel_async:: { AsyncPgConnection , RunQueryDsl } ;
20+ use futures_util:: { TryStreamExt , future} ;
21+ use http:: request:: Parts ;
22+ use indexmap:: { IndexMap , IndexSet } ;
23+ use std:: str:: FromStr ;
2624
2725#[ derive( Debug , Deserialize , FromRequestParts , utoipa:: IntoParams ) ]
2826#[ from_request( via( Query ) ) ]
@@ -62,21 +60,29 @@ impl ListQueryParams {
6260 }
6361}
6462
63+ #[ derive( Debug , Serialize , utoipa:: ToSchema ) ]
64+ pub struct ListResponse {
65+ versions : Vec < EncodableVersion > ,
66+
67+ #[ schema( inline) ]
68+ meta : ResponseMeta ,
69+ }
70+
6571/// List all versions of a crate.
6672#[ utoipa:: path(
6773 get,
6874 path = "/api/v1/crates/{name}/versions" ,
6975 params( CratePath , ListQueryParams , PaginationQueryParams ) ,
7076 tag = "versions" ,
71- responses( ( status = 200 , description = "Successful Response" ) ) ,
77+ responses( ( status = 200 , description = "Successful Response" , body = inline ( ListResponse ) ) ) ,
7278) ]
7379pub async fn list_versions (
7480 state : AppState ,
7581 path : CratePath ,
7682 params : ListQueryParams ,
7783 pagination : PaginationQueryParams ,
7884 req : Parts ,
79- ) -> AppResult < ErasedJson > {
85+ ) -> AppResult < Json < ListResponse > > {
8086 let mut conn = state. db_read ( ) . await ?;
8187
8288 let crate_id = path. load_crate_id ( & mut conn) . await ?;
@@ -113,7 +119,10 @@ pub async fn list_versions(
113119 . map ( |( ( v, pb) , aas) | EncodableVersion :: from ( v, & path. name , pb, aas) )
114120 . collect :: < Vec < _ > > ( ) ;
115121
116- Ok ( json ! ( { "versions" : versions, "meta" : versions_and_publishers. meta } ) )
122+ Ok ( Json ( ListResponse {
123+ versions,
124+ meta : versions_and_publishers. meta ,
125+ } ) )
117126}
118127
119128/// Seek-based pagination of versions by date
@@ -433,11 +442,20 @@ struct PaginatedVersionsAndPublishers {
433442 meta : ResponseMeta ,
434443}
435444
436- #[ derive( Serialize ) ]
445+ #[ derive( Debug , Serialize , utoipa :: ToSchema ) ]
437446struct ResponseMeta {
447+ /// The total number of versions belonging to the crate.
448+ #[ schema( example = 123 ) ]
438449 total : i64 ,
450+
451+ /// Query string to the next page of results, if any.
452+ #[ schema( example = "?page=3" ) ]
439453 next_page : Option < String > ,
454+
455+ /// Additional data about the crate's release tracks,
456+ /// if `?include=release_tracks` is used.
440457 #[ serde( skip_serializing_if = "Option::is_none" ) ]
458+ #[ schema( value_type = Option <Object >) ]
441459 release_tracks : Option < ReleaseTracks > ,
442460}
443461
0 commit comments