@@ -10,10 +10,9 @@ use crate::models::{User, Version as FullVersion, VersionDownload, VersionOwnerA
1010use crate :: schema:: { version_downloads, version_owner_actions, versions} ;
1111use crate :: util:: errors:: { AppResult , BoxedAppError , bad_request} ;
1212use crate :: views:: { EncodableVersion , EncodableVersionDownload } ;
13+ use axum:: Json ;
1314use axum:: extract:: FromRequestParts ;
1415use axum_extra:: extract:: Query ;
15- use axum_extra:: json;
16- use axum_extra:: response:: ErasedJson ;
1716use crates_io_database:: schema:: users;
1817use crates_io_diesel_helpers:: to_char;
1918use diesel:: prelude:: * ;
@@ -37,6 +36,37 @@ pub struct DownloadsQueryParams {
3736 include : Option < String > ,
3837}
3938
39+ #[ derive( Debug , Serialize , utoipa:: ToSchema ) ]
40+ pub struct DownloadsResponse {
41+ /// The per-day download counts for the last 90 days.
42+ pub version_downloads : Vec < EncodableVersionDownload > ,
43+
44+ /// The versions referenced in the download counts, if `?include=versions`
45+ /// was requested.
46+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
47+ pub versions : Option < Vec < EncodableVersion > > ,
48+
49+ #[ schema( inline) ]
50+ pub meta : DownloadsMeta ,
51+ }
52+
53+ #[ derive( Debug , Serialize , utoipa:: ToSchema ) ]
54+ pub struct DownloadsMeta {
55+ #[ schema( inline) ]
56+ pub extra_downloads : Vec < ExtraDownload > ,
57+ }
58+
59+ #[ derive( Debug , Serialize , Queryable , utoipa:: ToSchema ) ]
60+ pub struct ExtraDownload {
61+ /// The date this download count is for.
62+ #[ schema( example = "2019-12-13" ) ]
63+ date : String ,
64+
65+ /// The number of downloads on the given date.
66+ #[ schema( example = 123 ) ]
67+ downloads : i64 ,
68+ }
69+
4070/// Get the download counts for a crate.
4171///
4272/// This includes the per-day downloads for the last 90 days and for the
@@ -46,14 +76,13 @@ pub struct DownloadsQueryParams {
4676 path = "/api/v1/crates/{name}/downloads" ,
4777 params( CratePath , DownloadsQueryParams ) ,
4878 tag = "crates" ,
49- responses( ( status = 200 , description = "Successful Response" ) ) ,
79+ responses( ( status = 200 , description = "Successful Response" , body = inline ( DownloadsResponse ) ) ) ,
5080) ]
51-
5281pub async fn get_crate_downloads (
5382 state : AppState ,
5483 path : CratePath ,
5584 params : DownloadsQueryParams ,
56- ) -> AppResult < ErasedJson > {
85+ ) -> AppResult < Json < DownloadsResponse > > {
5786 let mut conn = state. db_read ( ) . await ?;
5887
5988 use diesel:: dsl:: * ;
@@ -78,7 +107,7 @@ pub async fn get_crate_downloads(
78107 . unwrap_or_default ( ) ;
79108
80109 let sum_downloads = sql :: < BigInt > ( "SUM(version_downloads.downloads)" ) ;
81- let ( downloads, extra , versions_and_publishers, actions) = tokio:: try_join!(
110+ let ( downloads, extra_downloads , versions_and_publishers, actions) = tokio:: try_join!(
82111 VersionDownload :: belonging_to( latest_five)
83112 . filter( version_downloads:: date. gt( date( now - 90 . days( ) ) ) )
84113 . order( (
@@ -101,18 +130,12 @@ pub async fn get_crate_downloads(
101130 load_actions( & mut conn, latest_five, include. versions) ,
102131 ) ?;
103132
104- let downloads = downloads
133+ let version_downloads = downloads
105134 . into_iter ( )
106135 . map ( VersionDownload :: into)
107136 . collect :: < Vec < EncodableVersionDownload > > ( ) ;
108137
109- #[ derive( Serialize , Queryable ) ]
110- struct ExtraDownload {
111- date : String ,
112- downloads : i64 ,
113- }
114-
115- if include. versions {
138+ let versions = if include. versions {
116139 let versions_and_publishers = versions_and_publishers. grouped_by ( latest_five) ;
117140 let actions = actions. grouped_by ( latest_five) ;
118141 let versions = versions_and_publishers
@@ -125,20 +148,15 @@ pub async fn get_crate_downloads(
125148 } )
126149 . collect :: < Vec < _ > > ( ) ;
127150
128- return Ok ( json ! ( {
129- "version_downloads" : downloads,
130- "versions" : versions,
131- "meta" : {
132- "extra_downloads" : extra,
133- } ,
134- } ) ) ;
135- }
151+ Some ( versions)
152+ } else {
153+ None
154+ } ;
136155
137- Ok ( json ! ( {
138- "version_downloads" : downloads,
139- "meta" : {
140- "extra_downloads" : extra,
141- } ,
156+ Ok ( Json ( DownloadsResponse {
157+ version_downloads,
158+ versions,
159+ meta : DownloadsMeta { extra_downloads } ,
142160 } ) )
143161}
144162
0 commit comments