@@ -18,6 +18,7 @@ use util::ResultExt;
pub fn router() -> Router {
Router::new()
.route("/extensions", get(get_extensions))
+ .route("/extensions/:extension_id", get(get_extension_versions))
.route(
"/extensions/:extension_id/download",
get(download_latest_extension),
@@ -32,29 +33,52 @@ pub fn router() -> Router {
struct GetExtensionsParams {
filter: Option<String>,
#[serde(default)]
+ ids: Option<String>,
+ #[serde(default)]
max_schema_version: i32,
}
-#[derive(Debug, Deserialize)]
-struct DownloadLatestExtensionParams {
- extension_id: String,
+async fn get_extensions(
+ Extension(app): Extension<Arc<AppState>>,
+ Query(params): Query<GetExtensionsParams>,
+) -> Result<Json<GetExtensionsResponse>> {
+ let extension_ids = params
+ .ids
+ .as_ref()
+ .map(|s| s.split(',').map(|s| s.trim()).collect::<Vec<_>>());
+
+ let extensions = if let Some(extension_ids) = extension_ids {
+ app.db
+ .get_extensions_by_ids(&extension_ids, params.max_schema_version)
+ .await?
+ } else {
+ app.db
+ .get_extensions(params.filter.as_deref(), params.max_schema_version, 500)
+ .await?
+ };
+
+ Ok(Json(GetExtensionsResponse { data: extensions }))
}
#[derive(Debug, Deserialize)]
-struct DownloadExtensionParams {
+struct GetExtensionVersionsParams {
extension_id: String,
- version: String,
}
-async fn get_extensions(
+async fn get_extension_versions(
Extension(app): Extension<Arc<AppState>>,
- Query(params): Query<GetExtensionsParams>,
+ Path(params): Path<GetExtensionVersionsParams>,
) -> Result<Json<GetExtensionsResponse>> {
- let extensions = app
- .db
- .get_extensions(params.filter.as_deref(), params.max_schema_version, 500)
- .await?;
- Ok(Json(GetExtensionsResponse { data: extensions }))
+ let extension_versions = app.db.get_extension_versions(¶ms.extension_id).await?;
+
+ Ok(Json(GetExtensionsResponse {
+ data: extension_versions,
+ }))
+}
+
+#[derive(Debug, Deserialize)]
+struct DownloadLatestExtensionParams {
+ extension_id: String,
}
async fn download_latest_extension(
@@ -76,6 +100,12 @@ async fn download_latest_extension(
.await
}
+#[derive(Debug, Deserialize)]
+struct DownloadExtensionParams {
+ extension_id: String,
+ version: String,
+}
+
async fn download_extension(
Extension(app): Extension<Arc<AppState>>,
Path(params): Path<DownloadExtensionParams>,
@@ -1,4 +1,5 @@
use chrono::Utc;
+use sea_orm::sea_query::IntoCondition;
use super::*;
@@ -10,37 +11,83 @@ impl Database {
limit: usize,
) -> Result<Vec<ExtensionMetadata>> {
self.transaction(|tx| async move {
- let mut condition = Condition::all().add(
- extension::Column::LatestVersion
- .into_expr()
- .eq(extension_version::Column::Version.into_expr()),
- );
+ let mut condition = Condition::all()
+ .add(
+ extension::Column::LatestVersion
+ .into_expr()
+ .eq(extension_version::Column::Version.into_expr()),
+ )
+ .add(extension_version::Column::SchemaVersion.lte(max_schema_version));
if let Some(filter) = filter {
let fuzzy_name_filter = Self::fuzzy_like_string(filter);
condition = condition.add(Expr::cust_with_expr("name ILIKE $1", fuzzy_name_filter));
}
- let extensions = extension::Entity::find()
- .inner_join(extension_version::Entity)
- .select_also(extension_version::Entity)
- .filter(condition)
- .filter(extension_version::Column::SchemaVersion.lte(max_schema_version))
- .order_by_desc(extension::Column::TotalDownloadCount)
- .order_by_asc(extension::Column::Name)
- .limit(Some(limit as u64))
- .all(&*tx)
- .await?;
+ self.get_extensions_where(condition, Some(limit as u64), &tx)
+ .await
+ })
+ .await
+ }
- Ok(extensions
- .into_iter()
- .filter_map(|(extension, version)| {
- Some(metadata_from_extension_and_version(extension, version?))
- })
- .collect())
+ pub async fn get_extensions_by_ids(
+ &self,
+ ids: &[&str],
+ max_schema_version: i32,
+ ) -> Result<Vec<ExtensionMetadata>> {
+ self.transaction(|tx| async move {
+ let condition = Condition::all()
+ .add(
+ extension::Column::LatestVersion
+ .into_expr()
+ .eq(extension_version::Column::Version.into_expr()),
+ )
+ .add(extension::Column::ExternalId.is_in(ids.iter().copied()))
+ .add(extension_version::Column::SchemaVersion.lte(max_schema_version));
+
+ self.get_extensions_where(condition, None, &tx).await
})
.await
}
+ /// Returns all of the versions for the extension with the given ID.
+ pub async fn get_extension_versions(
+ &self,
+ extension_id: &str,
+ ) -> Result<Vec<ExtensionMetadata>> {
+ self.transaction(|tx| async move {
+ let condition = extension::Column::ExternalId
+ .eq(extension_id)
+ .into_condition();
+
+ self.get_extensions_where(condition, None, &tx).await
+ })
+ .await
+ }
+
+ async fn get_extensions_where(
+ &self,
+ condition: Condition,
+ limit: Option<u64>,
+ tx: &DatabaseTransaction,
+ ) -> Result<Vec<ExtensionMetadata>> {
+ let extensions = extension::Entity::find()
+ .inner_join(extension_version::Entity)
+ .select_also(extension_version::Entity)
+ .filter(condition)
+ .order_by_desc(extension::Column::TotalDownloadCount)
+ .order_by_asc(extension::Column::Name)
+ .limit(limit)
+ .all(tx)
+ .await?;
+
+ Ok(extensions
+ .into_iter()
+ .filter_map(|(extension, version)| {
+ Some(metadata_from_extension_and_version(extension, version?))
+ })
+ .collect())
+ }
+
pub async fn get_extension(&self, extension_id: &str) -> Result<Option<ExtensionMetadata>> {
self.transaction(|tx| async move {
let extension = extension::Entity::find()