collab: Store features provided by extensions in the database (#24303)

This PR adds new columns to the `extension_versions` table to record
which features an extension provides.

These `provides_*` columns are populated from the `provides` field on
the extension manifest.

We'll be able to leverage this data in the future for showing what an
extension provides in the extensions UI, as well as allowing to filter
by extensions that provide a certain feature.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2025-02-05 14:50:24 -05:00 committed by GitHub
parent 2f5abe2b5a
commit 59738f88c2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 140 additions and 4 deletions

View file

@ -391,6 +391,7 @@ async fn fetch_extension_manifest(
repository: manifest.repository,
schema_version: manifest.schema_version.unwrap_or(0),
wasm_api_version: manifest.wasm_api_version,
provides: manifest.provides,
published_at,
})
}

View file

@ -6,10 +6,11 @@ pub mod tests;
use crate::{executor::Executor, Error, Result};
use anyhow::anyhow;
use collections::{BTreeMap, HashMap, HashSet};
use collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use dashmap::DashMap;
use futures::StreamExt;
use rand::{prelude::StdRng, Rng, SeedableRng};
use rpc::ExtensionProvides;
use rpc::{
proto::{self},
ConnectionId, ExtensionMetadata,
@ -781,6 +782,7 @@ pub struct NewExtensionVersion {
pub repository: String,
pub schema_version: i32,
pub wasm_api_version: Option<String>,
pub provides: BTreeSet<ExtensionProvides>,
pub published_at: PrimitiveDateTime,
}

View file

@ -1,4 +1,3 @@
use std::collections::BTreeSet;
use std::str::FromStr;
use chrono::Utc;
@ -283,6 +282,39 @@ impl Database {
description: ActiveValue::Set(version.description.clone()),
schema_version: ActiveValue::Set(version.schema_version),
wasm_api_version: ActiveValue::Set(version.wasm_api_version.clone()),
provides_themes: ActiveValue::Set(
version.provides.contains(&ExtensionProvides::Themes),
),
provides_icon_themes: ActiveValue::Set(
version.provides.contains(&ExtensionProvides::IconThemes),
),
provides_languages: ActiveValue::Set(
version.provides.contains(&ExtensionProvides::Languages),
),
provides_grammars: ActiveValue::Set(
version.provides.contains(&ExtensionProvides::Grammars),
),
provides_language_servers: ActiveValue::Set(
version
.provides
.contains(&ExtensionProvides::LanguageServers),
),
provides_context_servers: ActiveValue::Set(
version
.provides
.contains(&ExtensionProvides::ContextServers),
),
provides_slash_commands: ActiveValue::Set(
version.provides.contains(&ExtensionProvides::SlashCommands),
),
provides_indexed_docs_providers: ActiveValue::Set(
version
.provides
.contains(&ExtensionProvides::IndexedDocsProviders),
),
provides_snippets: ActiveValue::Set(
version.provides.contains(&ExtensionProvides::Snippets),
),
download_count: ActiveValue::NotSet,
}
}))
@ -357,6 +389,8 @@ fn metadata_from_extension_and_version(
extension: extension::Model,
version: extension_version::Model,
) -> ExtensionMetadata {
let provides = version.provides();
ExtensionMetadata {
id: extension.external_id.into(),
manifest: rpc::ExtensionApiManifest {
@ -371,7 +405,7 @@ fn metadata_from_extension_and_version(
repository: version.repository,
schema_version: Some(version.schema_version),
wasm_api_version: version.wasm_api_version,
provides: BTreeSet::default(),
provides,
},
published_at: convert_time_to_chrono(version.published_at),

View file

@ -1,4 +1,6 @@
use crate::db::ExtensionId;
use collections::BTreeSet;
use rpc::ExtensionProvides;
use sea_orm::entity::prelude::*;
use time::PrimitiveDateTime;
@ -16,6 +18,58 @@ pub struct Model {
pub schema_version: i32,
pub wasm_api_version: Option<String>,
pub download_count: i64,
pub provides_themes: bool,
pub provides_icon_themes: bool,
pub provides_languages: bool,
pub provides_grammars: bool,
pub provides_language_servers: bool,
pub provides_context_servers: bool,
pub provides_slash_commands: bool,
pub provides_indexed_docs_providers: bool,
pub provides_snippets: bool,
}
impl Model {
pub fn provides(&self) -> BTreeSet<ExtensionProvides> {
let mut provides = BTreeSet::default();
if self.provides_themes {
provides.insert(ExtensionProvides::Themes);
}
if self.provides_icon_themes {
provides.insert(ExtensionProvides::IconThemes);
}
if self.provides_languages {
provides.insert(ExtensionProvides::Languages);
}
if self.provides_grammars {
provides.insert(ExtensionProvides::Grammars);
}
if self.provides_language_servers {
provides.insert(ExtensionProvides::LanguageServers);
}
if self.provides_context_servers {
provides.insert(ExtensionProvides::ContextServers);
}
if self.provides_slash_commands {
provides.insert(ExtensionProvides::SlashCommands);
}
if self.provides_indexed_docs_providers {
provides.insert(ExtensionProvides::IndexedDocsProviders);
}
if self.provides_snippets {
provides.insert(ExtensionProvides::Snippets);
}
provides
}
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]

View file

@ -1,6 +1,8 @@
use std::collections::BTreeSet;
use std::sync::Arc;
use rpc::ExtensionProvides;
use super::Database;
use crate::db::ExtensionVersionConstraints;
use crate::{
@ -39,6 +41,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: 1,
wasm_api_version: None,
provides: BTreeSet::default(),
published_at: t0,
},
NewExtensionVersion {
@ -49,6 +52,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: 1,
wasm_api_version: None,
provides: BTreeSet::default(),
published_at: t0,
},
],
@ -63,6 +67,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext2/repo".into(),
schema_version: 0,
wasm_api_version: None,
provides: BTreeSet::default(),
published_at: t0,
}],
),
@ -214,6 +219,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: 1,
wasm_api_version: None,
provides: BTreeSet::default(),
published_at: t0,
}],
),
@ -227,6 +233,7 @@ async fn test_extensions(db: &Arc<Database>) {
repository: "ext2/repo".into(),
schema_version: 0,
wasm_api_version: None,
provides: BTreeSet::default(),
published_at: t0,
}],
),
@ -320,6 +327,10 @@ async fn test_extensions_by_id(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: 1,
wasm_api_version: Some("0.0.4".into()),
provides: BTreeSet::from_iter([
ExtensionProvides::Grammars,
ExtensionProvides::Languages,
]),
published_at: t0,
},
NewExtensionVersion {
@ -330,6 +341,11 @@ async fn test_extensions_by_id(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: 1,
wasm_api_version: Some("0.0.4".into()),
provides: BTreeSet::from_iter([
ExtensionProvides::Grammars,
ExtensionProvides::Languages,
ExtensionProvides::LanguageServers,
]),
published_at: t0,
},
NewExtensionVersion {
@ -340,6 +356,11 @@ async fn test_extensions_by_id(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: 1,
wasm_api_version: Some("0.0.5".into()),
provides: BTreeSet::from_iter([
ExtensionProvides::Grammars,
ExtensionProvides::Languages,
ExtensionProvides::LanguageServers,
]),
published_at: t0,
},
],
@ -354,6 +375,7 @@ async fn test_extensions_by_id(db: &Arc<Database>) {
repository: "ext2/repo".into(),
schema_version: 0,
wasm_api_version: None,
provides: BTreeSet::default(),
published_at: t0,
}],
),
@ -387,7 +409,11 @@ async fn test_extensions_by_id(db: &Arc<Database>) {
repository: "ext1/repo".into(),
schema_version: Some(1),
wasm_api_version: Some("0.0.4".into()),
provides: BTreeSet::default(),
provides: BTreeSet::from_iter([
ExtensionProvides::Grammars,
ExtensionProvides::Languages,
ExtensionProvides::LanguageServers,
]),
},
published_at: t0_chrono,
download_count: 0,