@@ -5,13 +5,41 @@ use crate::schema::{
55} ;
66use crate :: util:: errors:: AppResult ;
77use crate :: views:: { EncodableCategory , EncodableCrate , EncodableKeyword } ;
8- use axum_extra:: json;
9- use axum_extra:: response:: ErasedJson ;
8+ use axum:: Json ;
109use diesel:: prelude:: * ;
1110use diesel_async:: { AsyncPgConnection , RunQueryDsl } ;
1211use futures_util:: FutureExt ;
1312use std:: future:: Future ;
1413
14+ #[ derive( Debug , Serialize , utoipa:: ToSchema ) ]
15+ pub struct SummaryResponse {
16+ /// The total number of downloads across all crates.
17+ #[ schema( example = 123_456_789 ) ]
18+ num_downloads : i64 ,
19+
20+ /// The total number of crates on crates.io.
21+ #[ schema( example = 123_456 ) ]
22+ num_crates : i64 ,
23+
24+ /// The 10 most recently created crates.
25+ new_crates : Vec < EncodableCrate > ,
26+
27+ /// The 10 crates with the highest total number of downloads.
28+ most_downloaded : Vec < EncodableCrate > ,
29+
30+ /// The 10 crates with the highest number of downloads within the last 90 days.
31+ most_recently_downloaded : Vec < EncodableCrate > ,
32+
33+ /// The 10 most recently updated crates.
34+ just_updated : Vec < EncodableCrate > ,
35+
36+ /// The 10 most popular keywords.
37+ popular_keywords : Vec < EncodableKeyword > ,
38+
39+ /// The 10 most popular categories.
40+ popular_categories : Vec < EncodableCategory > ,
41+ }
42+
1543/// Get front page data.
1644///
1745/// This endpoint returns a summary of the most important data for the front
@@ -20,9 +48,9 @@ use std::future::Future;
2048 get,
2149 path = "/api/v1/summary" ,
2250 tag = "other" ,
23- responses( ( status = 200 , description = "Successful Response" ) ) ,
51+ responses( ( status = 200 , description = "Successful Response" , body = inline ( SummaryResponse ) ) ) ,
2452) ]
25- pub async fn get_summary ( state : AppState ) -> AppResult < ErasedJson > {
53+ pub async fn get_summary ( state : AppState ) -> AppResult < Json < SummaryResponse > > {
2654 let mut conn = state. db_read ( ) . await ?;
2755
2856 let config = & state. config ;
@@ -37,10 +65,10 @@ pub async fn get_summary(state: AppState) -> AppResult<ErasedJson> {
3765 popular_categories,
3866 popular_keywords,
3967 ) = tokio:: try_join!(
40- crates:: table. count( ) . get_result:: < i64 > ( & mut conn) . boxed( ) ,
68+ crates:: table. count( ) . get_result( & mut conn) . boxed( ) ,
4169 metadata:: table
4270 . select( metadata:: total_downloads)
43- . get_result:: < i64 > ( & mut conn)
71+ . get_result( & mut conn)
4472 . boxed( ) ,
4573 crates:: table
4674 . inner_join( crate_downloads:: table)
@@ -100,25 +128,18 @@ pub async fn get_summary(state: AppState) -> AppResult<ErasedJson> {
100128 encode_crates( & mut conn, just_updated) ,
101129 ) ?;
102130
103- let popular_categories = popular_categories
104- . into_iter ( )
105- . map ( Category :: into)
106- . collect :: < Vec < EncodableCategory > > ( ) ;
107-
108- let popular_keywords = popular_keywords
109- . into_iter ( )
110- . map ( Keyword :: into)
111- . collect :: < Vec < EncodableKeyword > > ( ) ;
112-
113- Ok ( json ! ( {
114- "num_downloads" : num_downloads,
115- "num_crates" : num_crates,
116- "new_crates" : new_crates,
117- "most_downloaded" : most_downloaded,
118- "most_recently_downloaded" : most_recently_downloaded,
119- "just_updated" : just_updated,
120- "popular_keywords" : popular_keywords,
121- "popular_categories" : popular_categories,
131+ let popular_categories = popular_categories. into_iter ( ) . map ( Category :: into) . collect ( ) ;
132+ let popular_keywords = popular_keywords. into_iter ( ) . map ( Keyword :: into) . collect ( ) ;
133+
134+ Ok ( Json ( SummaryResponse {
135+ num_downloads,
136+ num_crates,
137+ new_crates,
138+ most_downloaded,
139+ most_recently_downloaded,
140+ just_updated,
141+ popular_keywords,
142+ popular_categories,
122143 } ) )
123144}
124145
0 commit comments